Csharp/C#教程:c#中的marshal c ++“char **”分享


c#中的marshal c ++“char **”

我从C ++调用C#方法并将char **作为参数传递。 它必须是char **因为我需要通过参数返回值。

c#代码:

[ExportDll("test", System.Runtime.InteropServices.CallingConvention.StdCall)] public static int test([MarshalAs(UnmanagedType.AnsiBStr)] ref string p) { Console.WriteLine(p); } 

用于调用函数的c ++代码:

 typedef int (__stdcall *MYPROC)(char **); VOID main(VOID) { HINSTANCE hinstLib; MYPROC MyProc; BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; hinstLib = LoadLibrary(TEXT("mydll.dll")); if (hinstLib != NULL) { ProcAdd = (MYPROC) GetProcAddress(hinstLib, "test"); if (NULL != ProcAdd) { fRunTimeLinkSuccess = TRUE; char s1[] = "test"; char *s2 = s1; char **s3 = &s2; (MyProc) (s3); cout << s3; } fFreeResult = FreeLibrary(hinstLib); } } 

传递char *很简单(在c#中删除ref,并在c ++中使用char *),但是当尝试传递char **时,我在线上调用函数时遇到运行时错误:(

在c#中,Console.WriteLine打印出正确的值,但在那之后,我收到一个错误:

 Windows has triggered a breakpoint in COMDynamicLoad.exe. This may be due to a corruption of the heap, which indicates a bug in COMDynamicLoad.exe or any of the DLLs it has loaded. This may also be due to the user pressing F12 while COMDynamicLoad.exe has focus. The output window may have more diagnostic information. 

我该怎么做?

你声明ref UnmanagedType.AnsiBStr但你期望一个char** 。 这不起作用,因为BSTR的引用不是char **。 有关编组声明的示例,请参阅字符串的默认编组。 这些是输入输出字符串的可能声明:

 PassStringRef2([in, out] BSTR *s); PassStringRef3([in, out] LPStr *s); PassStringRef4([in, out] LPWStr *s); 

和等效的C#编组声明是:

 PassStringRef2([MarshalAs(UnmanagedType.BStr)]ref String s); PassStringRef3([MarshalAs(UnmanagedType.LPStr)]ref String s); PassStringRef4([MarshalAs(UnmanagedType.LPWStr)]ref String s); 

你的char**声明相当于LPStr *s ,所以正确的编组是[MarshalAs(UnmanagedType.LPStr)]ref String s 。 但更好的选择是使用BSTR因为显式长度声明,并使用BSTR助手在C ++中操作它。

这可能是因为您使用指向字符串文字的char*这很糟糕,因为修改该内存是未定义的行为。

这会有用吗?

 public static int test([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] string[] p) 

在许多情况下并且看起来像这里的情况(参见Remus Rusanu接受的答案),在API声明中使用正确的编组属性,只需要在界面的两端互操作“粘合”开始“播放”彼此很好“并导致……

我在原帖后5个月添加了这个答案,因为这个问题及其答案在修复我最近的互操作错误方面非常有用,但没有直接提到有关许多互操作问题的非常可信的原因的信息,即:

内存所有权约定不匹配
(和/或在内存分配和释放方法中)。

2008年1月在MSDN杂志上发表的一篇题为“ 托管代码与非托管代码之间的密钥”的文章为我提供了内存所有权约定所需的信息。 实际上,本文提供了编组过程的完整概述。 它涵盖了具体的细节和例子

这篇文章非常有用,因为它收集了一份文档,并以一种可访问的方式提供信息,这些信息在十几个技术上权威但干燥[和经常“令人困惑的]参考文档中传播(参见关于微软文档的古老但有点开玩笑的笑话) )。
简而言之,它使其成为互操作解决方案的临时实施者的良好入门或复习

上述就是C#学习教程:c#中的marshal c ++“char **”分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/1011453.html

(0)
上一篇 2021年12月30日
下一篇 2021年12月30日

精彩推荐