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



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;
}

然后我尝试用BAT命令从命令行编译这个DLL:

"c:Program FilesMicrosoft Visual Studio 12.0VCbincl.exe" ^
    /clr /Fo /Z7 /D "NDEBUG" ^
    /ENTRY:Start ^
    "..LinksLinks.cpp"

不幸的是,我得到了这个错误:

LNK1561: Entry point must be defined

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

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

int Start(array<String ^> ^ argc)
{
    return 0;
}

在托管程序集上指定/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
);

真傻。Option/ENTRY是link.exe的参数,而不是cl.exe 的参数

使用以下BAT脚本,我可以强制我的程序集具有自定义入口点。唯一的问题是,在这种情况下,由于某种原因,链接器需要直接使用/SUBSYSTEM选项设置项目的类型。

"c:Program FilesMicrosoft Visual Studio 12.0VCbinlink.exe" ^
    /DLL /ENTRY:Start ^
    /SUBSYSTEM:CONSOLE ^
    /WX ^
    /OUT:Links.dll ^
    "Links.obj"

最新更新