gpt4 book ai didi

c# - 将结构从 C# 传递到非托管代码

转载 作者:太空宇宙 更新时间:2023-11-03 14:11:25 24 4
gpt4 key购买 nike

我已经为这个问题奋斗了一段时间,希望有人能提供帮助。我正在将 VB6 应用程序转换为 C#。我将要展示的所有内容在 VB6 中都能完美运行,但在 C# 中会失败。

我正在对 C dll 进行 API 调用,传递一个结构。该结构在 C 端修改了值,我应该在我的返回结构中看到修改后的值。

注意,Sig是int,Status是int,CLIENTID是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# 中针对使用这些结构的 C 中 API 的 PInvoke 声明:

    [DllImport("TheCDLL.dll", EntryPoint = "_Request@4", 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# 中,“结果”始终仅为 0。我猜我编码的方式一定有问题?我已经阅读了数十篇文章,并尝试了很多不同的方法来使它正常工作,但都没有成功。感谢您的帮助!

更新:现在我已经根据以下建议更新了代码(修复类型并清理最初编写的代码),我遇到了一个异常:

System.AccessViolationException: Attempted to read or write protected memory. This is        often an indication that other memory is corrupt.

我发现,只要我将请求结构中的“public int vers”更改为“public Int16 vers”,就会发生这种情况。想法?

最佳答案

UnmanagedType.Struct 实际上不适用于子结构;它使编码(marshal)拆收器将相关对象作为 VARIANT 传递。这不是你想要的。尝试删除除字符串(长度)、数组(也用于长度)和枚举类型(我在这里没有看到任何内容,但在我的 DLL 中它们是 UnmanagedType.I4)之外的所有 MarshalAs 语句并查看如果可行的话。

在你的 C# 结构中还有一些你的 C 版本中没有的额外东西,两个变量之间不匹配,你给定的 C 函数不返回任何东西,但你的 C# extern 期待一个 IntPtr .这些确实需要匹配才能使一切顺利进行。 (我猜这只是网站的简化,但需要牢记这一点。)

关于c# - 将结构从 C# 传递到非托管代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7757099/

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