【问题标题】:Platform Invoke, bool, and string平台调用、布尔值和字符串
【发布时间】:2011-04-23 13:27:30
【问题描述】:

假设一个dll包含以下函数

extern "C" __declspec(dllexport) void f(bool x)
{
   //do something
}
extern "C" __declspec(dllexport) const char* g()
{
   //do something else
}

我在 C# 中使用这些函数的第一个天真的方法如下:

[DllImport("MyDll.dll")]
internal static extern void f(bool x);
[DllImport("MyDll.dll")]
internal static extern string g();

第一个惊喜是 C++ bool 没有转换为 C# bool(奇怪的运行时行为,但没有崩溃)。所以我不得不将 bool 更改为 byte 并手动从一个转换为另一个。所以,第一个问题是,有没有更好的方法来编组 bool(注意这是 bool,而不是 BOOL)

第二个惊喜是 dll 函数返回的原始字符串被 C# 字符串所拥有,而不是像我预期的那样被复制,最终 C# 代码释放了 dll 返回的内存。我发现这一点是因为程序崩溃了,但后来我将返回类型更改为 sbyte* 并使用已经完成复制的指针手动初始化字符串。所以第二个问题是: 2.1:有没有更好的方法来防止编组的字符串拥有指针。 2.2:见鬼?!为什么 C# 会这样做?我的意思是,一个明显的情况是 dll 函数返回一个文字,而 C# 试图删除它...

提前致谢,希望我的问题不是含糊不清或难以理解。

【问题讨论】:

    标签: c# c++ c interop marshalling


    【解决方案1】:
    [DllImport("MyDll.dll")]
    internal static extern void f( [MarshalAs(UnmanagedType.I1)] bool x );
    [DllImport("MyDll.dll")]
    [return: MarshalAs(UnmanagedType.LPStr)]
    internal static extern string g();
    

    【讨论】:

      【解决方案2】:

      默认情况下,.NET 在 C++ BOOL(4 字节)和 .NET bool 类型之间自动编组。对于 C++ bool(单字节)类型,您需要指定如何编组:

      [DllImport("MyDll.dll")]
      internal static extern void f([MarshalAs(UnmanagedType.I1)] bool x);
      

      【讨论】:

      • @Darin:有趣的是我的一个朋友跟我说的一模一样,你猜怎么着?它没有用。如果相关,我正在使用 .Net1.1
      • 其实这是从 1.1 开始支持的。看这里msdn.microsoft.com/en-us/library/…
      • @Darin,@Vinzenz:我知道!我看到了那个确切的页面。并尝试过,但同样的错误行为仍在继续。只有当我使用字节时,一切才开始工作......但无论如何,谢谢,如果两个人说同样的话,那么我想我一定做错了什么......
      • 什么是错误行为?在 C# 中传递 true 时,你会在 C++ 中得到 0
      • @Darin:是的,完全正确,反之亦然。我在 C# 中传递 true,在 C++ 中传递 false,反之亦然。
      猜你喜欢
      • 2015-08-19
      • 2015-02-07
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-30
      • 2012-03-06
      • 2019-10-15
      相关资源
      最近更新 更多