如何修复“方法的类型与 PInvoke 不兼容”
How to fix 'Method's type is not PInvoke Compatible'
尝试 return 结构与 C++ 中的布局完全相同,问题是当 TCHAR rMsg[256]
包含在 C++ 结构中而 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public char rMsg;
包含在 C# 结构中时(两者都将在下面显示)我收到错误“方法的类型与 PInvoke 不兼容”。
我还应该指出 C++ 不是我的,我无法更改它,因为其他函数需要下面给出的结构布局。
我知道问题出在 TCHAR 上,因为当我在 C++ 和 C# 中注释掉相关行时,我没有收到错误。
我将我创建的 .dll(我还将在下面的代码中包含)调用到 return 一个结构,以便我知道我有正确的语法。
C++:
extern "C" {
__declspec(dllexport) tVDACQ_CallBackRecVal ( _stdcall TestAcq2())
{
//Just adding random values so I know it works.
tVDACQ_CallBackRecVal AR;
AR.rFlags = 1;
AR.rFrameHeight = 10;
AR.rFrameWidth = 10;
return AR;
}
}
//Struct
typedef struct {
int rFlags,
rType,
rEvent,
rSocket;
TCHAR rMsg[256]; //Has to stay as TCHAR
int rFrameWidth,
rFrameHeight;
short* rFrameBuffer;
union {
int rCaptureRows;
int rCaptureFrames;
};
int rCapturePercent;
void* rUserCallBackProc,
* rUserParam;
int rAborted;
void* rPacketData;
int rFGControl;
} tVDACQ_CallBackRecVal;
C#:
//Simply calling the .dll
[DllImport("C:\Users\jch\source\repos\FlatPanelSensor\x64\Debug\VADAV_AcqS.dll", EntryPoint = "TestAcq2", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern tVDACQ_CallBackRec TestAcq2();
[StructLayout(LayoutKind.Sequential)]
public struct tVDACQ_CallBackRec
{
public int rFlags;
public int rType;
public int rEvent;
public int rSocket;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string rMsg; //I believe this is the issue
public int rFrameWidth;
public int rFrameHeight;
public IntPtr rFrameBuffer;
public int rCaptureRows;
public int rCaptureFrames;
public int rCapturePercent;
public IntPtr rUserCallBackProc;
public IntPtr rUserParam;
public int rAborted;
public IntPtr rPacketData;
public int rFGControl;
}
//Then I just call the function
tVDACQ_CallBackRec testStruct= TestAcq2();
我希望结构具有所有已定义的组件,但我却收到标题中所述的错误。
同样,如果我不包括 TCHAR(c++ 结构)和字符串(c# 结构),那么我就不会得到错误,所以我知道这是根本问题,我不知道如何解决那部分。
编辑:
有关解决方案,请参阅@David Heffernan
的第一条评论
解决此问题的最简单方法是更改原型,以便通过 ref:
将结构作为参数传递给函数
void _stdcall TestAcq2(tVDACQ_CallBackRecVal *retval)
尝试 return 结构与 C++ 中的布局完全相同,问题是当 TCHAR rMsg[256]
包含在 C++ 结构中而 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public char rMsg;
包含在 C# 结构中时(两者都将在下面显示)我收到错误“方法的类型与 PInvoke 不兼容”。
我还应该指出 C++ 不是我的,我无法更改它,因为其他函数需要下面给出的结构布局。
我知道问题出在 TCHAR 上,因为当我在 C++ 和 C# 中注释掉相关行时,我没有收到错误。
我将我创建的 .dll(我还将在下面的代码中包含)调用到 return 一个结构,以便我知道我有正确的语法。
C++:
extern "C" {
__declspec(dllexport) tVDACQ_CallBackRecVal ( _stdcall TestAcq2())
{
//Just adding random values so I know it works.
tVDACQ_CallBackRecVal AR;
AR.rFlags = 1;
AR.rFrameHeight = 10;
AR.rFrameWidth = 10;
return AR;
}
}
//Struct
typedef struct {
int rFlags,
rType,
rEvent,
rSocket;
TCHAR rMsg[256]; //Has to stay as TCHAR
int rFrameWidth,
rFrameHeight;
short* rFrameBuffer;
union {
int rCaptureRows;
int rCaptureFrames;
};
int rCapturePercent;
void* rUserCallBackProc,
* rUserParam;
int rAborted;
void* rPacketData;
int rFGControl;
} tVDACQ_CallBackRecVal;
C#:
//Simply calling the .dll
[DllImport("C:\Users\jch\source\repos\FlatPanelSensor\x64\Debug\VADAV_AcqS.dll", EntryPoint = "TestAcq2", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern tVDACQ_CallBackRec TestAcq2();
[StructLayout(LayoutKind.Sequential)]
public struct tVDACQ_CallBackRec
{
public int rFlags;
public int rType;
public int rEvent;
public int rSocket;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string rMsg; //I believe this is the issue
public int rFrameWidth;
public int rFrameHeight;
public IntPtr rFrameBuffer;
public int rCaptureRows;
public int rCaptureFrames;
public int rCapturePercent;
public IntPtr rUserCallBackProc;
public IntPtr rUserParam;
public int rAborted;
public IntPtr rPacketData;
public int rFGControl;
}
//Then I just call the function
tVDACQ_CallBackRec testStruct= TestAcq2();
我希望结构具有所有已定义的组件,但我却收到标题中所述的错误。
同样,如果我不包括 TCHAR(c++ 结构)和字符串(c# 结构),那么我就不会得到错误,所以我知道这是根本问题,我不知道如何解决那部分。
编辑: 有关解决方案,请参阅@David Heffernan
的第一条评论解决此问题的最简单方法是更改原型,以便通过 ref:
将结构作为参数传递给函数void _stdcall TestAcq2(tVDACQ_CallBackRecVal *retval)