gpt4 book ai didi

c# - 将非 Blittable 结构从 C# 编码到 C++

转载 作者:行者123 更新时间:2023-11-30 04:26:42 28 4
gpt4 key购买 nike

我正在重写我公司在 C# 和 C++ 之间接口(interface)的库代码中过度设计且无法维护的部分。我已经开始研究 P/Invoke,但似乎没有多少可用的帮助。

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

我的问题是:

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

作为引用,这是我目前编写的一对结构:

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 属性,您可以告诉编码器它应该转换成什么。看这个article on Blittable and Non-Blittable Types了解更多信息

1 - What is the best way to pass strings? Some are short (device id's which can be set by us), and some are file paths (which may contain Asian characters)

通常推荐使用 StringBuilder,因为它最容易使用,但我经常使用普通字节数组。

2 - Should I pass an IntPtr to the C# struct or should I just let the Marshaller take care of it by putting the struct type in the function signature?

如果该方法需要一个指针,则传递一个 IntPtr,尽管在许多情况下您可以使用 ref,这取决于它的用途。如果它需要在同一个地方停留很长时间,那么我会使用 Marshal 手动分配内存并传递生成的 IntPtr。

3 - Should I be worried about any non-pointer datatypes like bools or enums (in other, related structs)? We have the treat warnings as errors flag set in C++ so we can't use the Microsoft extension for enums to force a datatype.

一旦您使用正确的编码属性设置了所有内容,我不明白您为什么需要担心。如果对属性有疑问,如果该结构仅被托管代码使用,则不会使用该属性。

4 - Is P/Invoke actually the way to go? There was some Microsoft documentation about Implicit P/Invoke that said it was more type-safe and performant.

无法对此发表评论,您已经进入了 Visual C++ 领域。

关于c# - 将非 Blittable 结构从 C# 编码到 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11416433/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com