C# DLL 转换为 .il,再转换为 C++ DLL:字符串问题

3

我正在尝试从C#中导出一些功能,以便在我的非托管C++应用程序中使用它。在我的测试项目中,我首先创建了一个C# DLL,并编写了一个简单的函数,将字符串写入文件。然后我使用ildasm将其转换为中间语言(.il文件)。.il文件中的函数如下:


  // =============== CLASS MEMBERS DECLARATION ===================

  .class public auto ansi beforefieldinit MyTest.CSharpExportClass extends 

  [mscorlib]System.Object
  {
  .method public hidebysig static void        modopt([mscorlib]System.Runtime.CompilerServices.CallConvStdcall)   ExportNameOfFunction2(string test) cil managed
    {
  .vtentry 1 : 1
  .export [1] as ExportNameOfFunction2
      // Code size       25 (0x19)
      .maxstack  2
      .locals init ([0] class [mscorlib]System.IO.TextWriter tw)
      IL_0000:  ldstr      "date.txt"
      IL_0005:  newobj     instance void [mscorlib]System.IO.StreamWriter::.ctor(string)
      IL_000a:  stloc.0
    IL_000b:  ldloc.0
    IL_000c:  ldarg.0
    IL_000d:  callvirt   instance void [mscorlib]System.IO.TextWriter::WriteLine(string)
    IL_0012:  ldloc.0
    IL_0013:  callvirt   instance void [mscorlib]System.IO.TextWriter::Close()
    IL_0018:  ret
  } // end of method CSharpExportClass::ExportNameOfFunction2

.method public hidebysig specialname rtspecialname instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method CSharpExportClass::.ctor

} // end of class MyTest.CSharpExportClass

我看到里面有关键字“ansi”...使用ilasm.exe将其转换为C++ DLL后,我尝试在我的C++应用程序中加载并使用此函数:


HMODULE hdll = LoadLibraryW(L"CpCsh.dll");
    if(!hdll)
    {       
        return(-1);
    }

    typedef void (__stdcall *_EXP_NAME_OF_FUNCT)(wchar_t*);
    _EXP_NAME_OF_FUNCT      ExportNameOfFunction;

    ExportNameOfFunction = (_EXP_NAME_OF_FUNCT)GetProcAddress(hdll, "ExportNameOfFunction2");

    if(ExportNameOfFunction == NULL)
    {
        return(-1);
    }

    ExportNameOfFunction(L"hello all");

但是这样只会将第一个字母(“h”)写入文件。如果我在C++中声明函数使用char而不是wchar_t,并使用“hello all”而不是L“hello all”,整个字符串就会被写入文件。
还有几点需要注意: ildasm选项:/nologo /quiet /out:MyTest.dll MyTest.il /unicode /DLL /resource=MyTest.res /optimize ilasm选项:/nologo /out:C:\temp\CpCsh.dll "MyTest.il" /DLL
感谢您的帮助!

你必须已经编辑了IL。你打算如何维护这段代码?可以使用C++/CLI包装器完成,你将从__declspec(dllexport)中获得导出桥接程序。而无需编辑IL。 - Hans Passant
写一个混合模式 DLL 怎么样? - Sandeep Singh Rawat
2个回答

2

这正是一个函数期望接收char[]但实际上接收了wchar_t[]的症状:第一个wchar_t的第二个字节为零,被解释为字符串结尾。

您可以使用dumpbin /exports yourdll.dll命令验证编译后的dll是否将其函数导出为char*参数。

您应该尝试找到ilasm的编译器开关,告诉它将其字符串视为宽字符。


我只能通过dumpbin看到函数名,但无法看到传递给函数的参数或它们的类型。 - Warpin

0

最终我采纳了Sandeep的建议,构建了一个C++混合模式DLL。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接