我一直在争取这个问题一段时间,并希望有人可以提供帮助。我将一个VB6应用程序转换为C#。我即将展示的所有东西在VB6中都很完美,但在C#中失败了。将结构传递给来自C#的非托管代码
我正在对C DLL进行API调用,传递一个结构。该结构在C端获得修改值,我应该在返回结构中看到修改后的值。
注意,西格是int,状态是一个int,和客户端ID是UINT_PTR。
这里是C结构:
typedef struct
{
short vers;
short flags;
short cmd;
short objtype;
DWORD id;
DWORD client;
char buf[MAX_TOOLBUF];
DWORD toolID;
NMSG msg;
DWORD caller;
CLIENTID clientID;
DWORD ticket;
ToolResult PTR result;
long spare[4];
} Request;
typedef struct
{
DWORD hwnd;
DWORD message;
DWORD wParam;
DWORD lParam;
} NMSG;
typedef struct
{
Sig sig;
short cnt;
Status error;
DWORD ticket;
DWORD toolID;
long spare[4];
} ToolResult;
以我的C#代码,我有以下结构定义为映射到C的结构之上:
[StructLayout(LayoutKind.Sequential)]
public struct NMSG
{
public int hWnd;
public int msg;
public int wParam;
public int lParam;
}
[StructLayout(LayoutKind.Sequential)]
public struct Request
{
public Int16 vers;
public Int16 flags;
public Int16 cmd;
public int16 objType;
public int id;
public int Client;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string buf;
public int toolID;
public NMSG msg;
public int caller;
public IntPtr clientID;
public int ticket;
public ToolResult result;
[MarshalAs(UnmanagedType.ByValArray, SizeConst= 4) ]
public int64[] spare;
}
这是该方法的装饰C代码:
SendRequest(Request PTR req)
{
....
}
这是我在C中使用这些str的API中的PInvoke声明uctures:
[DllImport("TheCDLL.dll", EntryPoint = "[email protected]", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void Request(ref Request req);
这里是填充结构,使得API调用我的C#代码:
Request req = new Request();
req.vers = 1;
req.toolID = 4000;
req.Client = 0;
req.cmd = 11;
req.objType = 1;;
req.id = 1;
req.msg.hWnd = Hwnd; // verified this is a valid window handle
req.msg.msg = 1327;
req.msg.wParam = 101;
req.msg.lParam = 0;
req.spare = new int[4];
req.buf = new string(' ', 260);
req.flags = 11;
Request(ref req);
的问题是,在VB6代码结构项目“结果”被充满在进行API调用后的值。在C#中,'result'总是只有0。我猜我的编组方式一定有问题吗?我已经阅读了数十篇文章,并尝试了很多不同的方式让这项工作没有成功。任何帮助表示赞赏!
更新:现在,我已经根据下面的建议(固定类型和清理最初编写的代码)更新的代码中,我得到一个异常:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
我发现只要我在Request结构中从'public int vers'更改为'public Int16 vers',就会发生这种情况。思考?
“VERS”出现在你的C#结构尺寸错误类型。 – Joe
'objtype'也是错误的大小。改为使用短。 – Hans
什么是无人值守SendRequest方法的返回值?你能给我们完整的定义吗? – Hans