Blittable构造从C#到C ++

我正在重写我公司的库代码的过度工程和不可维护的块,这些代码在C#和C ++之间进行接口。 我已经开始研究P / Invoke,但是看起来好像没有什么可访问的帮助。

我们将包含各种参数和设置的结构传递给非托管代码,因此我们正在定义相同的结构。 我们不需要在C ++端更改任何这些参数,但我们需要在P / Invoked函数返回后访问它们。

我的问题是:

  • 什么是传递字符串的最佳方式? 有些是短的(设备ID可以由我们设置),有些是文件路径(可能包含亚洲字符)
  • 我是否应该将IntPtr传递给C#结构,还是应该让Marshaller通过将结构类型放入函数签名来处理它?
  • 我是否应该担心任何非指针数据类型,如bools或枚举(在其他相关结构中)? 我们将治疗警告设置为C ++中的错误标志,因此我们不能使用微软扩展来枚举来强制数据类型。
  • P / Invoke实际上是要走的路吗? 有一些关于Implicit P / Invoke的微软文档说,它是更安全和更高效的。

    作为参考,这是我迄今为止编写的一对结构:

    C ++

    /**
        Struct used for marshalling Scan parameters from managed to unmanaged code.
    */
    struct ScanParameters
    {
        LPSTR deviceID;
        LPSTR spdClock;
        LPSTR spdStartTrigger;
        double spinRpm;
        double startRadius;
        double endRadius;
        double trackSpacing;
        UINT64 numTracks;
        UINT32 nominalSampleCount;
        double gainLimit;
        double sampleRate;
        double scanHeight;
        LPWSTR qmoPath; //includes filename
        LPWSTR qzpPath; //includes filename
    };
    

    C#

    /// <summary>
    /// Struct used for marshalling scan parameters between managed and unmanaged code.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct ScanParameters
    {
        [MarshalAs(UnmanagedType.LPStr)]
        public string deviceID;
        [MarshalAs(UnmanagedType.LPStr)]
        public string spdClock;
        [MarshalAs(UnmanagedType.LPStr)]
        public string spdStartTrigger;
        public Double spinRpm;
        public Double startRadius;
        public Double endRadius;
        public Double trackSpacing;
        public UInt64 numTracks;
        public UInt32 nominalSampleCount;
        public Double gainLimit;
        public Double sampleRate;
        public Double scanHeight;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string qmoPath;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string qzpPath;
    }
    

    blittable类型是一种在托管代码和非托管代码之间具有共同表示的类型,因此可以在它们之间很少或没有问题地传递,例如byte,int32等。

    非blittable类型没有共同的表示形式,例如System.Array,System.String,System.Boolean等。

    通过为非blittable类型指定MarshalAs属性,您可以告诉编组人员应将其转换为什么。 有关更多信息,请参阅关于Blittable和Non-Blittable类型的文章

    1 - 传递字符串的最佳方式是什么? 有些是短的(设备ID可以由我们设置),有些是文件路径(可能包含亚洲字符)

    通常推荐使用StringBuilder作为最简单的使用方式,但我经常使用普通字节数组。

    2 - 我应该将一个IntPtr传递给C#结构,还是应该让Marshaller通过将结构类型放入函数签名来处理它?

    如果该方法需要一个指针,然后传递一个IntPtr,尽管在很多情况下你可能会得到一个ref,这取决于它将被用于什么。 如果它需要在相同的地方呆很长时间,那么我会用Marshal手动分配内存并传递生成的IntPtr。

    3 - 我是否应该担心任何非指针数据类型,如bool或枚举(在其他相关结构中)? 我们将治疗警告设置为C ++中的错误标志,因此我们不能使用微软扩展来枚举来强制数据类型。

    一旦你用正确的编组属性设置了一切,我不明白为什么你需要担心。 如果有疑问放入属性中,如果该结构只能被托管代码使用,则该属性将不会被使用。

    4 - P / Invoke实际上是要走的路吗? 有一些关于Implicit P / Invoke的微软文档说,它是更安全和更高效的。

    无法对此发表评论,你在那里进入Visual C ++领域。

    链接地址: http://www.djcxy.com/p/66597.html

    上一篇: Blittable Structs from C# to C++

    下一篇: Marshall array in C++ struct in C# struct