c# - 在 C# 中编码(marshal) C++ "char**"

标签 c# c++ marshalling dynamic-linking

我正在从 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**。参见 Default Marshaling for Strings有关编码声明的示例。这些是输入输出字符串的可能声明:

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

和等效的 C# 编码(marshal)处理声明是:

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

您的 char** 声明等同于 LPStr *s,因此正确的编码(marshal)处理是 [MarshalAs(UnmanagedType.LPStr)]ref String s。但更好的选择是使用 BSTR,因为它有明确的长度声明,并在 C++ 中使用 BSTR helpers 对其进行操作。 .

关于c# - 在 C# 中编码(marshal) C++ "char**",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6471421/

相关文章:

c# - Silverlight:空数据网格

c# - 加载表单而不显示它

c++ - WinAPI:轨迹栏滚动开始通知

c++ - 如何避免直接链接到cmake中的库文件?

c# - 带字符的 Marshall 结构

c# - 无法在 C# 应用程序中为我的线程使用多个处理器组

c# - 使用 C# 安全地连接到 AWS MySQL 数据库

c++ - 为什么在 C++20 中将 std::vector::push_back 声明为 constexpr?

c# - 为什么此编码在 Mono 中有效但在 MS 中失败?

c++ - 从 dbus xml 生成文件时,如何告诉 qmake 包含标题?