我在提出这个问题之前提到this somewhat similar question,但无法解决我的问题
我正在寻找一个包含许多解决方案的旧应用程序。问题出现在其中一个解决方案中(比如说S)。情况如下:
/clr
选项
该/clr
并为其创建了一个头文件
函数声明和函数定义的.cpp文件;该
C#呼叫是在它下面进行的; P2编译好并发出警告:
警告LNK4098:defaultlib'MSVCRT'与使用其他lib冲突; 使用/ NODEFAULTLIB:库
现在有了这些,我在P1中得到3个链接器错误:
错误LNK2005:“private:__ thiscall type_info :: type_info(class type_info const&)“(?? 0type_info @@ AAE @ ABV0 @@ Z)已在 libcmtd.lib(typinfo.obj)
错误LNK2005:“private:class type_info& __thiscall type_info :: operator =(class type_info const&)“ (?? 4type_info @@ AAEAAV0 @ ABV0 @@ Z)已定义于 libcmtd.lib(typinfo.obj)
错误LNK1169:找到一个或多个多重定义的符号
许多在线论坛(包括本网站)都提供此错误。但不知怎的,我在尝试这些选项后无法修复它(我是.NET框架的新手) 重要的是,即使我从P2中删除了C#代码,也会出现相同的错误。
修复它的正确方法是什么?
更新:
P2只包含1个带有函数声明的头文件和1个带有函数定义的源文件,它是对C#方法的1行调用;例如
void Class::foo () { // A static function inside Class
std::string x = marshal_as<std::string>(C#_function);
// ...
}
新添加P2以使用/clr
进行编译(删除P2使解决方案编译正常)
我正在使用/MD[d]
选项编译P1和P2。并且P1抛出了上述错误。
如果我从静态库(.lib)创建P2到动态链接库(.dll),那么上述错误就会消失。对于未定义的引用,foo
本身会出现新的链接器错误:
错误LNK2019:未解析的外部符号“public:void __cdecl Class :: foo()“在函数中引用{P1的某个函数}
答案 0 :(得分:5)
我终于能够通过大量的试验和错误以及进出StackOverflow的互联网搜索来解决这个问题。至少连接器错误消失了,不知道其他什么东西可能弹出,但这是一个好兆头 我会尽量在下面记录:
如何链接同一项目下的两个dll,其中一个是/clr
,另一个是非clr
?
/clr
项目/clr
,如果它包含所有.cpp代码且没有.c代码到目前为止,这很好,但问题出现在新项目(P2)功能定义未与原始项目(P1)链接时。它会出现各种链接器错误。
VC ++ 2010的步骤适用于新手用户(像我一样)。
配置P1 :
Add -> New Project -> Other
languages -> VC++ -> CLR empty project
并命名(例如P2);在项目的相应部分中添加头文件和.cpp文件Properties -> Configuration Properties ->
C/C++ -> Code Generation -> Runtime Library to Multi threaded DLL:
/MD[d]
; Properties -> Configuration Properties -> C/C++ ->
General -> Additional Include Directories
下的路径;这样你就可以包括在内
P2的新头文件在P1的源文件中的任何位置Properties -> Common Properties ->
Framework and Reference -> Add New Reference
,您应该可以
在那里看到P2;只需添加它配置P2 :
Properties -> Common Properties ->
Framework and References -> Add New Reference -> <Select the C# or
whatever external DLL you would want to call from P2>
DLL
Properties
-> Configuration Properties -> General -> Project Defaults -> Configuration Type -> Dynamic Library (DLL)
Output Directory
和Intermediate Directory
也与P1 Properties -> Configuration Properties ->
Linker -> General -> Ignore Import Library -> No
;我这样做是因为
就像在P1中一样__declspec(dllexport)
(或__declspec(dllimport)
,但不确定
两件作品);我从this question和this question 通过上述步骤,构建成功!
可能会有一些错过的东西,并且由于我面临一些运行时问题。但是至少我能够在同一个解决方案下链接2个DLL项目,这些项目有和没有/clr
。
答案 1 :(得分:3)
嗯,你没有链接C#代码,这是不可能的,所以这不是问题的根源。警告是核心问题的第一个提示,您正在尝试链接使用/ MT编译的代码,因此依赖于libcmtd.lib(CRT的静态版本)。您的C ++ / CLI代码将始终使用/ MD进行编译,因此依赖于msvcrtd.lib,这是存储在DLL中的CRT版本,可以在多个模块之间共享。
您不能在一个可执行文件中混合使用两个版本的CRT,这就是链接器使用LNK4098进行对象的原因。当它看到type_info类实现的两个副本时,链接失败,一个来自libcmtd.lib,另一个来自msvcrtd.lib,并且无法确定你真正想要的那个。
此外,C ++ / CLI项目有一个严格的要求,即必须使用/ MD并与msvcrtd.lib链接,不支持CRT的静态版本。您必须返回使用/ MT编译代码的项目,并将设置更改为/ MD。项目+属性,C / C ++,代码生成,运行时库设置。不清楚哪个特定项目存在这个问题。请注意从其他地方获得的.lib文件,这些文件只是使用错误的设置进行编译。如果你不知道麻烦制造者是哪个,那么grep文件“-MTd”,.lib文件包含原始编译命令的副本。
答案 2 :(得分:3)
另一种解决方案是使您的项目成为混合模式可执行文件。您可以将不同的C ++文件编译为不同的东西。其中大部分都是这样,但您可以为各个C ++文件设置不同的编译器设置,并使用/clr
编译器标志编译那些。您可以直接从该C ++ / CLI代码调用.NET对象。
如何链接它们是为了拥有一个共同的头文件,它没有.NET方面,只是一个类或函数原型,并且在文件中有实现这是用/clr
编译的。
主要&#34;陷阱&#34;这是:
/clr
(如预编译的标头)和的文件,则需要禁用许多其他选项。你仍然可以在项目的其余部分拥有它,但不是那个。基本上,添加新文件,使用/clr
选项,然后开始检查编译器错误,取消检查和更改属性中的字段,直到它工作。.h
文件包含在您需要调用函数的位置(非托管)以及您实现它们的位置,即使用.cpp
编译的/clr
文件。 System
之类的.NET程序集引用等基本内容以及您的CLR部分所需的任何其他内容。与上面相反,编译器选项需要是每个文件,在这种情况下,程序集包括在项目范围内。因此,要非常小心,只需要为要编译的特定.cpp文件(可能只有1)设置/ clr即可访问.NET。其余的编译应该不受影响。然后只需从那些特定的C ++文件中调用托管静态方法(并在必要时实例化类)。
如果您想要一个有效的项目,请给我发一个PM,然后我会通过电子邮件向您发送一个完成此项目的2012项目。
编辑:这是项目:http://www.mediafire.com/download/rfhk5hx6x27fp0m/MixedModeExecutable.7z
将其纳入2012年的解决方案,然后进行编译。它应该&#34;只是工作&#34;对于事物。
至于如何制作:
String^
或其他任何东西)的函数和/或类,但是你可以转发声明指向将包含这些东西的类的指针。您将在示例项目中看到这一点。<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
文件中的第.vcxproj
行位于{{1}}文件中。它在附加项目中正确4.5。所以我试过了,这对我有用。如果没有,请检查附件,看看这对VS 2012是否有效。