为啥这个显式 P/Invoke 不起作用?

Posted

技术标签:

【中文标题】为啥这个显式 P/Invoke 不起作用?【英文标题】:Why this Explicit P/Invoke does not work?为什么这个显式 P/Invoke 不起作用? 【发布时间】:2010-06-10 14:25:25 【问题描述】:

以下 .net 到本机 C 代码不起作用,任何想法

extern "C" 
   TRADITIONALDLL_API int TestStrRef( __inout char* c)    
   int rc = strlen(c);
   std::cout << "the input to TestStrRef is: >>" << c << "<<" ;
   c = "This is from the C code ";
   return rc;
   
 

 [DllImport("MyDll.dll", SetLastError = true)]
 static extern int TestStrRef([MarshalAs(UnmanagedType.LPStr)] ref string s);
 String abc = "InOut string";
 TestStrRef(ref abc);

此时,Console.WriteLine(abc) 应该打印“This is from the C code”,但没有,有什么想法吗?

仅供参考 - 我有另一个不使用 ref 类型字符串的测试函数,它工作得很好

【问题讨论】:

首先让它在 C 中工作。 Native C - 它是 C .net - 不知道 :( 【参考方案1】:

您的代码在 C 端也有错误。 __inout 注释只是告诉编译器您可以更改“c”参数指向的缓冲区。但是指针本身位于堆栈中,如果您修改了“c”参数,则不会返回给调用者。 您的声明可能如下所示:

extern "C" 
   TRADITIONALDLL_API int TestStrRef( __inout char** c)    
   int rc = strlen(*c);
   std::cout << "the input to TestStrRef is: >>" << *c << "<<" ;
   *c = "This is from the C code ";
   return rc;
   
 

还有 C# 方面:

[DllImport("MyDll.dll", SetLastError = true)]
static extern int TestStrRef(ref IntPtr c);


    String abc = "InOut string";
    IntPtr ptrOrig = Marshal.StringToHGlobalAnsi(abc)        
    IntPtr ptr = ptrOrig; // Because IntPtr is structure, ptr contains copy of ptrOrig
    int len = TestStrRef(ref ptr);
    Marshal.FreeHGlobal(ptrOrig); // You need to free memory located to abc' native copy
    string newAbc = Marshal.PtrToStringAnsi(ptr); 
    // You cannot free memory pointed by ptr, because it pointed to literal string located in dll code.

【讨论】:

【参考方案2】:

这对你有用吗?基本上只需在 DllImport 语句中添加 CallingConvention = CallingConvention.Cdecl 即可。您可能还想指定CharSet(例如:CharSet:=CharSet.Unicode)

 [DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
 static extern int TestStrRef([MarshalAs(UnmanagedType.LPStr)] ref string s);

【讨论】:

为什么调用约定很重要?调用方法已经为 OP 工作了。

以上是关于为啥这个显式 P/Invoke 不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

extern 访问修饰符不起作用

为啥这个 CATransition 不起作用?

为啥这个重定向不起作用?

为啥这个 Check 约束不起作用?

我不明白为啥这个@selector 不起作用

为啥这个触发器不起作用?