C# DLL 到 .il,到 C++ DLL:字符串问题

发布于 2024-09-28 00:58:45 字数 2317 浏览 2 评论 0原文

我正在尝试从 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

任何帮助表示赞赏!

I'm trying to export some functionality from C# so I can use it in my unmanaged C++ app. On my test project, I first I create a C# DLL with a simple function to write a string to a file. I then use ildasm to turn this into an intermediate language (.il file). The function in .il looks like so:


  // =============== 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

I see the keyword "ansi" in there... After turning this into a C++ DLL using ilasm.exe, I try to load to use this function in my C++ app:


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");

But this will only write the first letter ("h") to file. If I declare the function as using char instead of wchar_t in C++, and use "hello all" instead of L"hello all" the whole string is written to file.

A few more notes:
ildasm options: /nologo /quiet /out:MyTest.dll MyTest.il /unicode /DLL /resource=MyTest.res /optimize

ilasm options: /nologo /out:C:\temp\CpCsh.dll "MyTest.il" /DLL

Any help is appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时常饿 2024-10-05 00:58:45

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

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

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

This is exactly the symptom of a function expecting a char[] but receiving a wchar_t[]: the second byte of the first wchar_t is zero, interpreted as end-of-string

You can verify if your compiled dll exports it's function as a char* argument by using the dumpbin /exports yourdll.dll command.

You should try to find the compiler switch for ilasm that tells it to treat it's strings as wide characters.

同尘 2024-10-05 00:58:45

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

I ended up going with Sandeep's suggestion and built a C++ mixed mode DLL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文