编译链接同名依赖库
⑴ 在QTCreate如何添加LIB依赖库进行编译
依照上述的格式,你就可以添加编译时需要的依赖库了。
这是一种正确的方法,不过在笔者还不知道这种方法的时候,笔者时通过修改Makefile的。在debug目录下,有一个Makefile文件,你可以通过在如下的方式:在Makefile里面找到
在这里进行添加。不过这种方式的有一个问题:那就是当.pro的文件变化的时候,Makefile就会被重新组织和生成,这个时候LIBS 就会被改变,你需要再次添加,不然又会编译出错。希望这个方法对大家有用!
⑵ 我编译A静态库的时候依赖了B静态库,我编译的程序依赖A静态库和B静态库,这样B静态库是不是会有重复的部分
静态库在程序的链接阶段被复制到了程序中。
你用依赖这个词。
程序编译一般需经预处理、编译、汇编和链接几个步骤。
在链接步骤中,静态库才会被复制。
因为静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系。
存在几个链接?
那么就几分拷贝。
⑶ Linux动态库多重依赖,编译问题!!!!!!
这只能说明一个问题,你依赖的库本隐基销身有问题,没有把它的依锋档赖都加进去,也就是你例子中的①灶游libb.so依赖liba.so;,你应该在生成libb.so的时候,把对liba.so的依赖加进去,这样应该就没有问题了。
⑷ c脚本在不同系统中编译和链接依赖的库文件有何区别
问题1,
区别很大,跨OS编译的区别就在于OS的本质区别,有一下几点:
a, 字节排序,一个int型的数据在windows里是由高地址存到低地址的4个字节的(假设是32位机器),但是在某些UNIX服务器,如AIX,它的排序方式就相反的,所以当程序被编译成低级语言(例如汇编)的时候,内存及CPU的处理就会截然相反
b, 字长,有些unix服务器是64位的,但大多WINDOWS是32位,那么定义一个整形的时候就有用8个字节和4个字节的区别,字长不一样,那么执行起来用对内存的使用也自然就不一样咯。
c,所谓的库,也是由编译器编译出来的,在不同的OS下,由同一个代码编译出来的库也会不一样。
d,编译器也各不相同,也会导致编译出程序不完全相同。
e,所谓的调用,也就是将程序和库一起打包,然后在找到库里面所定义的函数罢了
综上,当一个程序或者库要从其他OS搬到另一个不同规格的OS上的时候,一定要重新编译一下草能确保程序跑起来不发生错误,求其原因也就是因为OS的本质区别,兼容的话,其实就是看OS是否在规格上有没有本质区别
二,库文件的编译是单向的,所以无法取回源码,
.a库的打包例: ar r libabc.a a.o b.o c.o
将a.o b.o c.o 合并打包成libabc.a。注意哦(.a一定要以lib开始.a结束哦)
WIN下我不是很在行,你说的lib大包应该没错。
三,我不是很清楚
希望对你有帮助,我2年工作的精华
⑸ AIX系统下,采用xlC_r编译、链接多个动态库,不同的动态库有同名的类,导致程序异常退出,如何解决
用域操作来区分同名类, 使用的时候指明域名就可以了
比如这样: 你把其中一个同名类用域名来操作,另一个用全局域操作,当然,你也可以都采用命名空间来处理.
m.cpp:#include <stdio.h>
m.cpp:namespace james
m.cpp:{
m.cpp: #include "james.h"
m.cpp:}
m.cpp:class AA
m.cpp:{
m.cpp:public:
m.cpp: AA() { printf("A() %s\n", __FILE__); }
m.cpp: ~AA() { printf("~A()\n"); }
m.cpp:};
m.cpp://using namespace james; // 这句如果放开就会命名冲突, 你可以试试,如果要方便使用,就是两个类用两个不同的命名空间,然后在某个文件中如果仅仅用到其中一个,那么你可以用using 关键字指定其中一个, 就和你原来的使用一样了.
m.cpp:int main()
m.cpp:{
m.cpp: james::AA o;
m.cpp: AA o2;
m.cpp:}
james.h:#include <stdio.h>
james.h:
james.h:class AA
james.h:{
james.h:public:
james.h: AA() { printf("A() %s\n", __FILE__); }
james.h: ~AA() { printf("~A()\n"); }
james.h:};
Makefile:
Makefile:all: m.cpp james.h
Makefile: g++ $^
⑹ OpenCV静态库编译与链接
以OpenCV-4.0.0为例说明在Ubuntu环境下的静态库编译与链接方法:
opencv依赖第三方的库,所以当把opencv编译成静态库的时候,注意要把它运行时必要的依赖库也编译进来,opencv源码内有自己的3rdparty,主要有:libjpeg、libpng、libtiff、libzlib、libwebp、libprotobuf、ffmpeg(用到video时编译)、libgtk(用于显示界面显示,服务器部署不会用到),可以通过cmake -LA来查看配置的编译信息,再根据信息考虑把opencv的哪些mole编译进来。
链接时指定opencv的静态库以及依赖的库。另外需要注意头文件的问题,通过CMakeLists把opencv加入项目编译时,由于opencv编译完成后要install才会把所用的头文件集中拷贝到一个地方,所以事先将头文件拷贝到了项目的opencv目录下。
⑺ C#代码编译动态链接库(DLL)
1.visual studio 新建-项目-类库
2.一定要选.NET FrameWork
4.配置名字芹简路径
或者引用-添加引用
windows路径:桐知
C:\Program Files\Unity\Hub\Editor<version-number>\Editor\Data\Managed\UnityEngine
macOS路局首消径:
/Applications/Unity/Hub/Editor/<version-number>/Unity.app/Contents/Managed/UnityEngine
10.添加引用完成后【生成】/【重新生成】
11.生成后的文件在刚才选的路径/默认路径
⑻ g++ 编译命令中依赖的动态库如果还依赖别的库,命令怎么设置
第一步,我先从简单的调用出发,定义了一个简单的函数,该函数仅仅实现一个整数加法求和:
LIBEXPORT_API int mySum(int a,int b){ return a+b;}
C# 导入定义:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern int mySum (int a,int b);
}
在C#中调用测试:
int iSum = RefComm.mySum(,);
运行查看结果iSum为5,调用正确。第一步试验完成,说明在C#中能够调用自定义的动态链接库函数。
第二步,我定义了字符串操作的函数(简单起见,还是采用前面的函数名),返回结果为字符串:
LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a); return a;}
C# 导入定义:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, string b);
}
在C#中调用测试:
string strDest="";
string strTmp= RefComm.mySum("45", strDest);
运行查看结果 strTmp 为"45",但是strDest为空。我修改动态链接库实现,返回结果为串b:
LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a) return b;}
修改 C# 导入定义,将串b修改为ref方式:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, ref string b);
}
在C#中再调用测试:
string strDest="";
string strTmp= RefComm.mySum("45", ref strDest);
运行查看结果 strTmp 和 strDest 均不对,含不可见字符。再修改 C# 导入定义,将CharSet从Auto修改为Ansi:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, string b);
}
在C#中再调用测试:
string strDest="";
string strTmp= RefComm. mySum("45", ref strDest);
运行查看结果 strTmp 为"45",但是串 strDest 没有赋值。第二步实现函数返回串,但是在函数出口参数中没能进行输出。再次修改 C# 导入定义,将串b修改为引用(ref):
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, ref string b);
}
运行时调用失败,不能继续执行。
第三步,修改动态链接库实现,将b修改为双重指针:
LIBEXPORT_API char *mySum(char *a,char **b){sprintf((*b),"%s",a); return *b;}
C#导入定义:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, ref string b);
}
在C#中调用测试:
string strDest="";
string strTmp= RefComm. mySum("45", ref strDest);
运行查看结果 strTmp 和 strDest 均为"45",调用正确。第三步实现了函数出口参数正确输出结果。
第四步,修改动态链接库实现,实现整数参数的输出:
LIBEXPORT_API int mySum(int a,int b,int *c){ *c=a+b; return *c;}
C#导入的定义:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern int mySum (int a, int b,ref int c);
}
在C#中调用测试:
int c=0;
int iSum= RefComm. mySum(,, ref c);
运行查看结果iSum 和c均为5,调用正确。
经过以上几个步骤的试验,基本掌握了如何定义动态库函数以及如何在 C# 定义导入,有此基础,很快我实现了变长加密函数在 C# 中的调用,至此目标实现。
三、结论
在 C# 中调用 C++ 编写的动态链接库函数,如果需要出口参数输出,则需要使用指针,对于字符串,则需要使用双重指针,对于 C# 的导入定义,则需要使用引用(ref)定义。
对于函数返回值,C# 导入定义和 C++ 动态库函数声明定义需要保持一致,否则会出现函数调用失败。定义导入时,一定注意 CharSet 和 CallingConvention 参数,否则导致调用失败或结果异常。运行时,动态链接库放在 C# 程序的目录下即可,我这里是一个 C# 的动态链接库,两个动态链接库就在同一个目录下运行。
⑼ c++动态链接库可不可以有两个同名函数,静态链接库呢,可以有两个同名函数吗
单个动态库可以有帆兄弊两个同名函数,但是不能同时导出来,不然会出错,不同动态库可以有同名函数,运行时加载不会有问题态族,尘哗编译时指定会有想不到的运行结果。
单个静态库可以有同名函数,但是某些编译器不支持,不同静态库之间也可以有同名函数,但如果函数签名也一致,使用的时候会编译错。
⑽ C++编译链接错误
C++常见编译/链接错误及其解决办法
1. 解决error LNK2005: ___crtExitProcess 已经在 LIBCMTD.lib(crt0dat.obj) 中定义
有的时候, 在 Debug 模式下编译没问题, 换到 Release 模式就发生一堆问题.
典型的例子, 就是因为 c++ runtime library 设定不同, 所造成的重复定义连结错误.
而另一个常见的例子是 专案与 library 使用不同的字符集合设定
(如: 一个用 Unicode Character Set, 另一个用 Multi-Byte Character Set)
这个错误发生原因, 有可能是
1. 你 link 的 lib 使用 C++ Multi-threaded DLL (/MD)
2. 而你的 source 使用的 C++ runtime library 是 Multi-threaded (/MT)
导致重复定义
解决方法:
两个使用相同的 C++ runtime library.例如都使用 static 的 Multi-threaded (/MT).
2. 错误 1error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) 已经在 LIBCMT.lib(typinfo.obj) 中定义 MSVCRTD.lib
项目 -> 属性 -> c/C++ -> 代码生成 -> 运行时库 设置为: 多线程调试 DLL (/MDd)
被引用的库和调用的程序编译选项不同,需要改成一致后编译
3.#pragma once与 #ifndef的区别
为了避免同一个文件被include多次
1 #ifndef方式
2 #pragma once方式
在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一些细微的区别。
方式一:
#ifndef __SOMEFILE_H__
#define __SOMEFILE_H__
... ... // 一些声明语句
#endif
方式二:
#pragma once
... ... // 一些声明语句
#ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况
#pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。
方式一由语言支持所以移植性好,方式二 可以避免名字冲突
4.error LNK2019: 无法解析的外部符号 __imp__PathCombineW
PathCombine是Shell api 需要引入库#pragma comment( lib, "shlwapi.lib")
5.error C2662: "MyClass::GetName()”: 不能将“this”指针从“const MyClass”转换为“MyClass &”
bool MyClass::operator==(const MyClass* n1) const
{return GetName() == n1->GetName();}
原因是不能在const函数中调用对象的非const方法,MyClass中的GetName()必须是const的。
6.template 模板
模板声明和定义必须在同一个文件中,而且只有实例话模板类型时才编译模板实例
7.error C2275: “MyClass”: 将此类型用作表达式非法 MyClass.Instance();
原因:Instance是静态方法,用.引用会出错。应该是MyClass::Instance()
8.error LNK2019: 无法解析的外部符号 "public: __thiscall MyClass(void)
原因:只声明了构造函数,MyClass(); ,但未定义。 可以定义空函数,或者直接注释掉,使用默认构造函数。
9.error C2504: “testing”: 未定义基类
class PackToolTest : testing.Test {}
原因:Test是testing命名空间下的一个类,需要用域操作符,testing::Test
还有一个问题,缺少基类继承权限(public、protected、private)
10.error C2864: “MyClass::_nullpack”: 只有静态常量整型数据成员才可以在类中初始化
class MyClass {string _nullpack = "test";}
原因:c++ 中,成员变量不能在声明时初始化,而是在构造函数初始化列表中先初始化
11.error LNK2019: 无法解析的外部符号_WinMain@16int main()
原因:由于创建的是Win32 Project,和Win32 console Project的链接库不同
方法1:在程序最开始的地方加上以下语句
#pragma comment(linker, "/subsystem:console ")
方法2:project > > setting > > 在link 的project options 中将/subsystem:windows(console)删了
12.类似“已经在 msvcprtd.lib(MSVCP80D.dll) 中定义”问题
vs2005 Debug /Release需要分别配制
分析一下错误来源,会发现:
1. 错误来源主要是重复定义的问题,而且重复定义的基本上都是VC Runtime和Standard C++ Library中的函数
2. LIBCMT和LIBCPMT为Release下的Lib,本来不应该出现在Debug版本的链接的Lib中
3. 重复定义的问题主要出现在:LIBCMT, LIBCPMT, MSVCPRTD, MSVCRTD
来看看出问题的LIB是那些:
1. LIBCMT:C Runtime库的多线程静态链接的Release版本
2. LIBCPMT:C++ Standard Library的多线程静态链接的Release版本
3. MSVCPRTD:C++ Standard Library的多线程DLL的Debug版本
4. MSVCRTD:C Runtime Library的多线程DLL的Debug版本
当 前我们的配置是多线程DLL的Debug版,因此3和4是应该出现在link的列表中的,不属于多余。而后两者则是只是当多线程静态链接Release版 中才会出现。这提示我在项目中加入的ANTLR.LIB可能是造成这个问题的根源,因为静态库的编译选项很容易和主程序发生冲突,并且根据实际信息我们可 以看出ANTLR.LIB应该是用多线程静态链接的Release版本来编译的。
解决方法:
1、首先查看编译项目依赖的其他项目的运行时库是否一致
2、如果不一致,改为同样的运行时库,如在下编译的是:“多线程调试 DLL (/MDd)”,现在需要把所有的依赖项目的运行时库都改为一致的库,就OK了。
13.error C2143: 语法错误 : 缺少“;”(在“*”的前面)
原因:产生错误处,某类型未include,可能头文件名拼写错误、头文件名已更改
14.error C2572: “MyClass::Invoke”: 重定义默认参数 : 参数 2
string MyClass::Invoke(const CParam& paraObj, INVOKETYPE type = ASYN)
原因:默认参数,只需在声明时指定。方法定义的时候无需指定默认参数。
string MyClass::Invoke(const CParam& paraObj, INVOKETYPE type )
{ ... }
15.错误 C2558 没有可用的复制构造函数或复制构造函数声明为“explicit”
试图复制其复制构造函数为 private 的类。在大多数情况下,不应复制具有 private 复制构造函数的类。通用编程技术声明 private 复制构造函数以防止直接使用类。该类本身可能无用,或需要另一个类才能正常工作。
尝试复制其复制构造函数为 explicit 的类。用 explicit 声明复制构造函数会阻止将类的对象传递到函数或从函数返回类的对象。
原因: 拷贝构造函数、赋值函数参数必须用const修饰
16.不能创建抽象类对象
原因: 1. 存在虚函数未实现; 2. 由于疏忽重载虚函数格式错误(此问题需要仔细检查才能发现); 3. 虚函数名称与系统中已有的虚函数重名,导致重载失败(这点很纳闷)。
17.没有找到MSCRV80D.dll
工程属性: 配置类型 由 exe 改成 lib 后生成, 然后再改回来,运行时会出现 “没有找到MSCRV80D.dll” 的异常
解决方法:
工程属性:MFC的使用 由 “使用标准Windows库” 改成 “在静态库中使用MFC“ 生成 ,然后再改回来,生成、运行 OK
18.CVTRES : fatal error CVT1100: 重复的资源。type:MANIFEST, name:1, language:0x0409
另一个则提示为:
LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
已经到了链接期,应该说,问题就不像编译通不过那么别扭了,而查阅MSDN关于这两个问题的说明,终于找到了解决的方法,现简单的陈述如下:
首先,出现这两个问题的原因都是一个,即文件中的现有资源文件和新资源字符串表 ID 冲突。微软也给出了解决这个问题的方法,但是,在现有的情况下,这个方法是靠不住的,因为,不可能不使用wx.rc资源。所以,一个变通的解决方法就是:
工程属性->配置属性-> 清单工具->输入和输出->嵌入清单,选择[否],即可。