通过互操作调用方法,该方法返回结构的实例
Call a method through Interop which returns an instance of a struct
我是互操作的新手,需要从 C# 调用一个托管C++方法,该方法返回以下struct
的实例:
typedef struct DataBlock_ {
unsigned char data[10240];
unsigned int numberOfBytes;
unsigned long int startAddr;
} DataBlock;
返回实例的 C++ 方法声明如下:
__declspec(dllexport) DataBlock getDefaultPass( void )
{
DataBlock default_pass = {
{
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF
},
32,
0xFFE0
};
return default_pass;
}
我已经在 C# 中声明了结构和方法,如下所示:
public static partial class My
{
[StructLayout(LayoutKind.Sequential)]
public struct DataBlock
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10240)]
public byte[] data;
//public fixed byte data[10240]; <-- this requires 'unsafe' but still doesn't work
public UInt32 numberOfBytes;
public UInt32 startAddr;
}
[DllImport("my.dll")]
static public extern DataBlock getDefaultPass( );
[DllImport("my.dll")]
static public extern byte sendPassword(DataBlock data);
}
我从 C# 调用该方法,如下所示:
var defaultPassword = My.getDefaultPass();
var response = My.sendPassword(defaultPassword);
但是getDefaultPass()
的召唤抛出
类型的未处理异常 "System.Runtime.InteropServices.MarshalDirectiveException"发生在 控制台应用程序1.exe
其他信息:方法的类型签名不是 PInvoke 相容。
基于这个问题,我尝试将 data
的声明更改为 public fixed byte data[10240]
并将结构标记为 unsafe
,但随后该方法返回一个实例,numberOfBytes
和 startAddr
设置为 0,随后对 sendPassword()
的调用失败(请注意,在此答案中,后续调用使用指向结构的指针而不是实例本身, 就像我的情况一样(。那么我应该如何从 C# 调用方法呢?
该项目面向 .NET 3.5 和 x86。
提前感谢任何帮助。
struct
很好 - 它满足在 P/Invoke 中用作返回值的所有规则。
您需要使用正确的调用约定(在您的情况下为 CallingConvention.Cdecl
(。
一些编译器还使用了一个额外的优化,其中大结构(例如您的(通过引用传递,而不是返回。可以在 C# 中复制它,如下所示:
static public extern void getDefaultPass(out DataBlock data);
为了完整起见并补充 Luaan 的答案,由于问题中的C++方法没有参数,我想介绍方法确实有参数的情况,特别是当该方法采用 2 个或更多参数时,它与out
参数的位置有关。
考虑C++方法
__declspec(dllexport) DataBlock readText(char * dataArray , int bytesToRead)
在 C# 方法中,out
参数应该是第一个还是最后一个并不明显。与框架将out
参数作为最后一个参数的约定相反(例如 TryParse
(,这里必须是第一个参数,否则调用将失败:
[DllImport("my.dll", CallingConvention = CallingConvention.Cdecl)]
static public extern void readText(out DataBlock dataBlock, string dataArray, int bytesToRead);
- 从父类方法返回子类对象
- 获取从C++中同一类中的构造函数调用的方法返回的值
- 让bool方法返回其他整数
- 不能将方法返回的值用于另一个方法
- 从私有成员变量的成员方法返回unique_ptr
- 我的模板类方法返回错误类型?
- QtQuick - qml:28:错误:未知方法返回类型:自定义类型
- 我无法使用C++指针指向类方法返回的 std::vector
- 对象引用中的字段以不同的方法返回不同的值
- 类方法返回指向具有模板的类成员的指针
- 如何将字符串从 C++/CLI 方法返回到调用它的非托管C++
- 从工厂方法返回的ComPtr的引用计数增加两次
- 如何使用 SFINAE 从 end() 方法返回 (const_) 迭代器
- Arduino trim() 和 replace() 方法返回从 'void' 到非标量类型'String'请求的转换
- 从类方法返回 "const char*" 作为 std::string&
- 如何使用 "get" 方法返回类的私有 std::unique_ptr 成员
- 可能从单个方法返回不同类型的对象
- qml 未知方法返回类型:ArchiveFile*,即使调用了 qmlRegisterUncreatableType
- 如何从方法返回静态常量 int std::array?
- 当从其他方法返回 vector 时,C++无法访问矢量元素