我正在重写我公司的C#和C ++之间接口的过度工程和不可维护的库代码。我已经开始研究P / Invoke,但似乎没有太多的可访问帮助。
我们将包含各种参数和设置的结构传递给非托管代码,因此我们要定义相同的结构。我们不需要在C ++方面更改任何这些参数,但我们确实需要在P / Invoked函数返回后访问它们。
我的问题是:
作为参考,这是我到目前为止写的一对结构:
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;
}
答案 0 :(得分:2)
blittable类型是一种在托管代码和非托管代码之间具有共同表示的类型,因此可以在它们之间传递而几乎没有问题,例如: byte,int32等。
非blittable类型没有共同的表示,例如System.Array,System.String,System.Boolean等。
通过为非blittable类型指定MarshalAs属性,您可以告诉编组器应该将其转换为什么。 有关详细信息,请参阅此article on Blittable and Non-Blittable Types
1 - 传递字符串的最佳方法是什么?有些是短的(设备ID可以由我们设置),有些是文件路径(可能包含亚洲字符)
通常建议使用StringBuilder作为最容易使用的,但我经常使用普通字节数组。
2 - 我应该将IntPtr传递给C#结构,还是应该让Marshaller通过将结构类型放在函数签名中来处理它?</ p>
如果方法期望一个指针然后传递一个IntPtr,尽管在很多情况下你可能会得到一个ref,这取决于它将用于什么。如果它需要长时间停留在同一个地方,那么我会手动为Marshal分配内存并传递生成的IntPtr。
3 - 我是否应该担心任何非指针数据类型,如bool或枚举(在其他相关结构中)?我们将处理警告作为在C ++中设置的错误标志,因此我们不能使用Microsoft扩展来强制使用枚举数据类型。
一旦你使用正确的编组属性设置了所有内容,我就不明白为什么你需要担心。如果对该属性存在疑问,如果该结构仅被托管代码使用,则该属性将不会被使用。
4 - P / Invoke实际上是走的路吗?有一些关于Implicit P / Invoke的Microsoft文档说它更安全,性能更高。
无法对此发表评论,您将进入Visual C ++领域。