【问题标题】:Second value not getting passed to C++ function during pinvoke在 pinvoke 期间第二个值未传递给 C++ 函数
【发布时间】:2017-05-25 09:02:39
【问题描述】:

我有一个 c++ 函数,我使用 pinInvoke 从 c# 调用它。以下是我的 cpp 方法-

int test(DWORD verb,DWORD verb2 )
{
    return verb2 *100;
}

我的功能暴露为 -

extern "C" {
    __declspec(dllexport) int test(DWORD verb, DWORD verb2);
}

以下是我调用上述方法的 c# 代码:

public class API
{
    [DllImport("mydll.dll", EntryPoint = "test", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
    [return: MarshalAs(UnmanagedType.U4)]
    public static extern uint test(
        [MarshalAs(UnmanagedType.U8)]ulong verb,
        [MarshalAs(UnmanagedType.U8)]ulong verb2);

    static void Main(string[] args)
    {
        uint x = DPAPI.test(26,10);
        Console.Write("result is-"+x);
    }
}

这里第二个值被传递为 0,所以会出现错误的结果。传递值时我做错了什么吗?

我尝试过的:

我对 Pinvoke 比较陌生。所以我尝试调试看看值是否没有传递给c++代码或者c++代码是否没有返回正确的值。我发现传递的值本身是错误的。

【问题讨论】:

  • 这个链接可以帮助你:stackoverflow.com/questions/39951473/…
  • 我不认为它的类型是这里的问题,因为第一个值被正确传递。
  • @SomeshDhal 好吧,鉴于您使用的类型在内存方面是您应该使用的类型的两倍,这肯定没有帮助。
  • 值在堆栈上传递。该函数接收两个 32 位值。所以它从堆栈中取出 64 位。这意味着它将您传递的第一个 64 位值解释为两个单独的 32 位值。如果您在启用堆栈不平衡 MDA 的情况下运行,您将收到有关堆栈不平衡的警告。

标签: c# c++ .net dll pinvoke


【解决方案1】:

DWORD 是 32 位无符号整数。您将其映射到 64 位类型。那就是问题所在。您的 p/invoke 应该是:

[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int test(uint verb, uint verb2);

请注意,我从DllImport 属性中删除了不必要的EntryPoint 和错误的SetLastError

我也想知道你为什么选择DWORD。除非您将这些值传递给 Win32 函数,否则使用内部类型可能更有意义。为什么不在 C++ 代码中使用 intunsigned int

【讨论】:

  • 解决了!!但是第一个变量如何获得正确的值?
  • 我在对问题的评论中解释了这一点。
  • 不太确定有没有这样的地方。有一天我会写一篇关于这个主题的指南,涵盖所有经常出现的问题......
  • 今天又出现了一个类似的事情。所以我传递了两个值(长为 unmanagedtype.I8 和 int 作为 unmanagedtype.I4),并且在我的 c++ 代码中这两个值都是 DWORD。根据您上面的解释,它不应该起作用。但在我的情况下,它适用于 64 位机器,但在 32 位的情况下,第二个值始终为 0。我知道我做错了什么,但想知道它为什么会这样。注意解释这种行为吗?
  • X64 调用约定在寄存器中传递参数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-26
  • 2019-07-05
相关资源
最近更新 更多