在c#中编组(将结构传递给非托管类型)

时间:2009-04-26 00:08:15

标签: c# pinvoke

我有一个c ++ dll,它公开了以下函数

long func(struct name * myname)
{
     strcpy(myname->firstname,"rakesh");
     strcpy(myname->lastname,"agarwal");
     return S_OK;
}

struct name
{
    char firstname[100];
    char lastname[100];
}

我想从C#应用程序调用此函数,所以我执行以下操作:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
unsafe public struct name
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=100)]
    public string firstname;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
    public string lastname;
} ;


[DllImport("C++Dll.dll")]
public unsafe static extern long func(name[] myname);

name[] myname = new name[1];
func(myname);

应用程序构建成功。运行C#application .exe时,函数func()被成功调用,并且能够在dll中成功填充字段。但是当函数返回到C#应用程序时,变量myname仍然会为结构字段(firstnamelastname)包含空值。

请建议更改,以便我能够填充myname的字段值(以便在函数func()完成执行后,变量myname->firstname包含“rakesh”和{{ 1}}包含“agarwal”。

注意:StringBuilder不能在结构中使用。

2 个答案:

答案 0 :(得分:7)

不是使用数组,而是通过引用传递struct。对于PInvoke调用,ref struct将被转换为指向struct的指针。 ref参数还告诉CLR在两个方向上编组数据,到本机代码然后再次退出。

[DllImport("C++Dll.dll")]
public unsafe static extern long func(ref name myname);

此外,如果您正在进行大量的互操作,我建议您查看PInvoke互操作助手(link)。该工具将自动将大多数C类型定义(包括结构,枚举,联合和函数指针)转换为相应的C#或VB.Net类型。它还将转换包含这些类型的签名。

答案 1 :(得分:3)

将导入声明为public unsafe static extern long func(ref name myname),并将其命名为:

name myname = new name();
func(ref myname);

顺便说一下,你可能不需要对名称结构或导入声明进行不安全的声明。