如何使用命令行参数 /ENTRY 在 C++/CLI DLL 中定义入口点

Sky*_*ner 4 dll c++-cli

cl.exe 中有一个选项可以使用命令行属性 /ENTRY 在 DLL 中定义自定义入口点。不幸的是,它没有提供如何使用它的示例。

http://msdn.microsoft.com/en-us/library/f9t8842e%28v=vs.100%29.aspx

我创建了支持 /CLR 的托管 C++ DLL,并将主函数的名称替换为“Start”:

int Start(int argc, char *argv[])
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然后我尝试使用以下 BAT 命令从命令行编译此 DLL:

"c:\Program Files\Microsoft Visual Studio 12.0\VC\bin\cl.exe" ^
    /clr /Fo /Z7 /D "NDEBUG" ^
    /ENTRY:Start ^
    "..\Links\Links.cpp"
Run Code Online (Sandbox Code Playgroud)

不幸的是,我收到此错误:

LNK1561: Entry point must be defined
Run Code Online (Sandbox Code Playgroud)

问题:我到底应该传递什么作为 /ENTRY 参数?

编辑:正如下面 Hans 的评论中提到的,函数曾经是 DLL 中的入口点,需要有另一个签名,所以我更正了上面的示例。下面介绍的函数是 EXE 文件入口点的示例,特别是因为它的参数中有托管类型。

int Start(array<String ^> ^ argc)
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Ben*_*igt 5

在托管程序集上指定/ENTRY是一个非常糟糕的主意,因为现在 C++ 运行时库中的所有 .NET Framework 支持代码都不会被执行。全局 C++ 对象的初始化程序也没有机会运行。而且工作线程上可能会出现内存泄漏,因为 C++ 运行时库足够智能,可以在需要时执行线程本地初始化,但由于它没有接收线程分离事件,因此无法进行清理。另一方面,C++/CLI 程序集始终动态链接到运行时 DLL,因此至少该库DllMain将接收线程通知,并且运行时本身使用的资源不会泄漏。

只需保留DllMainCRTStartup库提供的入口点,并提供一个名为DllMain库入口点将调用的函数即可。

MSDN 上有大量有关 C++/CLI 托管程序集中的初始化代码的文档:

需要注意的重要事情之一是签名DllMain(同样,它不是实际的入口点,它是从库提供的入口点调用的)

BOOL WINAPI DllMain(
  _In_  HINSTANCE hinstDLL,
  _In_  DWORD fdwReason,
  _In_  LPVOID lpvReserved
);
Run Code Online (Sandbox Code Playgroud)

  • @SkyScanner:我对一些具体后果添加了更多解释。 (2认同)