c# 中的编组(将结构传递给非托管类型)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/789977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Marshalling in c# ( Passing structure to an unmanaged type )
提问by
I have a c++ dll which exposes the following function
我有一个 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];
}
I want to call this function from a C# application , so I do the following :
我想从 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);
The application builds successfully. When the C# application .exe is run, the function func()
is called successfully and it is able to populate the fields successfully inside the dll. But when the function returns to the C# application, the variable myname
still conatins null values for the struct fields(firstname
and lastname
).
应用程序构建成功。当 C# 应用程序 .exe 运行时,该函数func()
被成功调用并且能够成功填充 dll 中的字段。但是当函数返回到 C# 应用程序时,该变量myname
仍然包含结构域(firstname
和lastname
)的空值。
Please suggest changes so that I am able to populate the fields values of myname
(so that after the function func()
finishes execution, the variable myname->firstname
contains "rakesh" and myname->lastname
contains "agarwal".
请提出更改建议,以便我能够填充myname
( 以便在函数func()
完成执行后,变量myname->firstname
包含“rakesh”和“agarwal myname->lastname
”。
Note: StringBuilder cannot be used inside the structure.
注意:StringBuilder 不能在结构内部使用。
回答by itowlson
Declare the import as public unsafe static extern long func(ref name myname)
, and call it as:
将导入声明为public unsafe static extern long func(ref name myname)
,并将其称为:
name myname = new name();
func(ref myname);
You probably don't need the unsafe declarations on the name structure or import declaration, by the way.
顺便说一下,您可能不需要名称结构或导入声明上的不安全声明。
回答by JaredPar
Instead of using an array, pass the struct by reference. For a PInvoke call, a ref struct will be translated into a pointer to the struct. The ref argument also tells the CLR to marshal data in both directions, to native code and then back out again.
不使用数组,而是通过引用传递结构。对于 PInvoke 调用,ref 结构将被转换为指向该结构的指针。ref 参数还告诉 CLR 将两个方向的数据编组到本机代码,然后再返回。
[DllImport("C++Dll.dll")]
public unsafe static extern long func(ref name myname);
Also, if you're doing a lot of interop work I suggest you check out the PInvoke interop assistant (link). This tool will automatically convert the majority of C type definitions (including structs, enums, unions and function pointers) into their corresponding C# or VB.Net types. It will additionally convert signatures which contain these types.
此外,如果您正在进行大量互操作工作,我建议您查看 PInvoke 互操作助手(链接)。该工具会自动将大多数 C 类型定义(包括结构、枚举、联合和函数指针)转换为它们对应的 C# 或 VB.Net 类型。它还会转换包含这些类型的签名。