首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在PINVOKE中传递带有字符串数据的struct?

如何在PINVOKE中传递带有字符串数据的struct?
EN

Stack Overflow用户
提问于 2013-06-29 20:40:29
回答 2查看 2.7K关注 0票数 1

我不得不把带有字符串数据的结构从C#代码传递到C++ dll。

c++代码

代码语言:javascript
复制
typedef struct 
{
    LPCSTR lpLibFileName;
    LPCSTR lpProcName;
    LPVOID pPointer1;
    LPVOID pPointer2;
} ENTITY, *PENTITY, *LPENTITY;
extern "C" __declspec(dllexport) int Test(LPENTITY entryList, int size);

int Test(LPENTITY entryList, int size)
{
    for (int i = 0; i < size; i++)
    {
        ENTITY e = entryList[i];
        // the char* value doesn't get passed correctly.
        cout << e.lpLibFileName << e.lpProcName << endl;
    }
    return 0;
}

c#代码

代码语言:javascript
复制
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
private class Entity
{
    public string lpLibFileName;
    public string lpProcName;
    public IntPtr pPointer1;
    public IntPtr pPointer2;
}

[DllImport("cpp.dll")]
private static extern int Test(
    [In, Out, MarshalAs(UnmanagedType.LPArray)]Entity[] entities,
    int size);

static void Main(string[] args)
{
    var entries = new[]
        {
            new Entity
                {
                    lpLibFileName = "comdlg32",
                    lpProcName = "PrintDlgExW",
                    pPointer1 = Marshal.GetFunctionPointerForDelegate(new PrintDlgEx(PrintDlgExCallback)),
                    pPointer2 = IntPtr.Zero,
                },
            new Entity
                {
                    lpLibFileName = "shell32",
                    lpProcName = "ShellAboutW",
                    pPointer1 = Marshal.GetFunctionPointerForDelegate(new ShellAbout(ShellAboutCallback)),
                    pPointer2 = IntPtr.Zero,
                },
        };
    var ret = Test(entries, entries.Length);
}

PINVOKE已触发,但无法正确传递lpLibFileName和lpProcName等char*数据。我错过了什么吗?如何纠正它?

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-06-30 01:43:22

您的代码将C#类映射到本机结构。因为C#类是引用类型,所以它将被编组为引用。因此,您的代码传递了一个引用数组,该数组被编组为本机端的指针数组。

但是本机代码需要一个指向值类型结构数组的指针。因此,最简单的解决方案是将Entity的声明更改为struct而不是class

我能看到的其他问题:

  1. 本机代码似乎使用了cdecl调用约定。您需要更改C#代码以匹配.
  2. 您正在使用Out修饰数组参数。不能将对string字段的修改封送回托管代码。
  3. 您需要确保传递给GetFunctionPointerForDelegate的委托保持活动状态,以阻止收集委托。
票数 0
EN

Stack Overflow用户

发布于 2013-06-29 22:01:27

当传递像自定义结构数组这样的参数时,在定义自己的数据结构时使用'struct‘而不是'class’。在我把它改回struct之后,一切都运行得很好。

代码语言:javascript
复制
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
private struct Entity
{
    public string lpLibFileName;
    public string lpProcName;
    public IntPtr pPointer1;
    public IntPtr pPointer2;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17380270

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档