我有一个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
仍然会为结构字段(firstname
和lastname
)包含空值。
请建议更改,以便我能够填充myname
的字段值(以便在函数func()
完成执行后,变量myname->firstname
包含“rakesh”和{{ 1}}包含“agarwal”。
注意:StringBuilder不能在结构中使用。
答案 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);
顺便说一下,你可能不需要对名称结构或导入声明进行不安全的声明。