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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 01:14:41  来源:igfitidea点击:

Marshalling in c# ( Passing structure to an unmanaged type )

c#pinvoke

提问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 mynamestill conatins null values for the struct fields(firstnameand lastname).

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

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->firstnamecontains "rakesh" and myname->lastnamecontains "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 类型。它还会转换包含这些类型的签名。