BYVAL编组C-结构,在C#中返回值 [英] Marshaling byval C-structure as return value in C#

查看:281
本文介绍了BYVAL编组C-结构,在C#中返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有非托管代码:

...
typedef struct foo  
{  
 int  a;  
 bool b
 int  c;  
} FOO,*LPFOO;
....
__declspec(dllexport) FOO __stdcall GetFoo()  
{  
   FOO f;  
   <some work>  
   return f;   
}  
....



我已经宣布C#原型的getFoo功能:

I've declare C# prototype for GetFoo function:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct Foo
    {
      public int  a;  
      public bool b
      public int  c; 
    };

    [DllImport("foo.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    [return:MarshalAs( UnmanagedType.Struct)]        
    private static extern Foo GetFoo();



但是,当我从C#代码调用的getFoo我送花儿给人有MarshalDirectiveException-方法的类型签名不是PInvoke的兼容。我应该怎样申报C#原型?

But when I calling GetFoo from C# code I alway have MarshalDirectiveException- Method's type signature is not PInvoke compatible. How I should declare C# prototype?

推荐答案

是的,这回的结构功能,往往很难与互操作。这样的结构具有为<青霉> blittable 的,以便在PInvoke的编组可以传递一个指针的功能,准备好写入返回值。被blittable是指在托管代码的结构布局需要是相同的结构的非托管布局。如果没有,那么一个副本需要作出的PInvoke的编组不希望使该副本。

Yes, functions that return a structure tend to be difficult to interop with. Such a structure has to be blittable so the pinvoke marshaller can pass a pointer to the function, ready for it to write the return value. Being "blittable" means that the structure layout in managed code needs to be identical to the unmanaged layout of the structure. If it is not then a copy needs to be made, the pinvoke marshaller does not want to make that copy.

布尔的类型是互操作的问题,不同的运行时做出不同的选择。它往往是4个字节的C(比较到Windows BOOL类型,也为PInvoke的默认值),2个字节的COM互操作(即VARIANT_BOOL),1个字节的C ++和其他运行时,包括CLR。失配的问题。

The bool type is an interop problem, different runtimes made different choices. It tends to be 4 bytes in C (compare to the Windows BOOL type, also the default for pinvoke), 2 bytes in COM interop (aka VARIANT_BOOL), 1 byte in C++ and other runtimes, including the CLR. The mismatch is the problem.

字节的替换它,它会工作。要注意的是有很多在代码中的错误,我做了这个版本的作品:

Replace it with byte and it will work. Beware that there were a lot of mistakes in your code, I made this version work:

using System;
using System.Runtime.InteropServices;

class Program {
    static void Main(string[] args) {
        Foo value = GetFoo();
    }
    [StructLayout(LayoutKind.Sequential)]
    private struct Foo {
        public int a;
        public byte b;
        public int c;
    };
    [DllImport(@"c:\projects\consoleapplication3\debug\cpptemp10.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_GetFoo@0")]
    private static extern Foo GetFoo(/*int CoreIndex*/);
}







typedef struct foo  
{  
    int  a;  
    bool b;
    int  c;  
} FOO,*LPFOO;

extern "C" __declspec(dllexport) 
FOO __stdcall GetFoo()  
{  
    FOO f;  
    f.a = 42;
    f.b = true;
    f.c = 101;
    return f;   
}  

这篇关于BYVAL编组C-结构,在C#中返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆