【问题标题】:conversation with typedef variable in c++在 C++ 中与 typedef 变量的对话
【发布时间】:2015-03-24 14:22:48
【问题描述】:

我有这样的 c++ 类型定义

typedef void* ScreenNode;

并像这样在我的 c++ 代码中使用它

ret = InitNode("factory", &g_screen_node, 128, 128, EN_C1Dev);

**EN_C1Dev 是一个枚举

我的 typedef 变量是一个 void 指针,InitNode 通过更改指针值“g_screen_node”返回一个值。

现在我在具有此定义的 C# 程序内的 dll 中使用此函数

c++代码

extern "C" __declspec(dllexport) int CB_initNode(ScreenNode* p_g_screen_node,int width,int heigth,EN_DevType EN_C1Dev) { int ret = 0;

    //InitNode ----------------------------------------------------------------
    ret = InitNode("factory", p_g_screen_node, 128, 128, EN_C1Dev);
    return ret;
}

dll定义类

[DllImport(dllName)]
        public static extern
            int CB_initNode(out IntPtr g_screen_node, int width, int heigth, EN_DevType EN_C1Dev);

最后是我的主程序

IntPtr g_screen_node = new IntPtr();
ret = BBIA.CB_initNode(out g_screen_node , 128, 128, EN_DevType.EN_C3Dev);

CB_initNode 函数返回错误代码,g_screen_node 未返回预期值并停留在 0x00000000!

【问题讨论】:

  • 除非你,否则不要在C#中使用指针。 (提示:您不必这样做。将 P/Invoke 签名更改为使用 ref int g_screen_node 并传递 ref ab。这不会修复您的错误,但您仍然应该更改它。)

标签: c# c++ variables dll typedef


【解决方案1】:

按顺序回答问题的各个部分:

  1. 您应该查阅InitNode 的文档(或源代码,如果没有可用的文档)以了解InitNode 的输入和输出参数的含义。 最有可能该方法实际上分配和初始化ScreenNode 并将opaque pointer 返回给调用者——其内部实现被隐藏。但是,您的问题中没有足够的信息来确定这一点。

    我对您问题其余部分的回答假设这是真的。如果没有,请使用来自InitNode 的适当文档更新您的问题,然后我们可以再次回答。

  2. c++ 代码。你需要用extern "C" __declspec(dllexport)来装饰你的函数:

    extern "C" __declspec(dllexport) int CB_initNode(ScreenNode *p_g_screen_node,int width,int heigth, EN_DevType EN_C1Dev)
    {
        int ret = 0;
    
        //InitNode ----------------------------------------------------------------
        ret = InitNode("factory", p_g_screen_node, 128, 128, EN_C1Dev);
        return ret;
    }
    

    您还需要传入指向ScreenNode 的指针(即双指针),以便将InitNode() 中设置的指针值传递出去。

  3. 然后在您的 c# extern declaration 中,将返回的指针定义为 out IntPtr

    [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
    public static extern int CB_initNode(out IntPtr g_screen_node, int width, int heigth, EN_DevType EN_C1Dev);
    
  4. 然后在主程序中:

    IntPtr g_screen_node;
    var ret = BBIA.CB_initNode(out g_screen_node, 128, 128, EN_DevType.EN_C3Dev);
    

然后,如果您需要将ScreenNode 传递回同一个库,您将使用之前返回的IntPtr。完成后,不要忘记释放它 - 大概您正在使用的库也有一个方法。

最后,您没有说明EN_DevType 是什么,但我猜它是enum。如果是这样,您应该检查您的值是否正确。如果不是enum,那么我对您问题的回答可能需要更新。

更新

如果InitNode 需要知道传入void ** 指针的当前值,因为它是预分配或预初始化的,则签名如下:

    [DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
    public static extern int CB_initNode(ref IntPtr g_screen_node, int width, int heigth, EN_DevType EN_C1Dev);

    IntPtr g_screen_node = // However you initialize are supposed to allocate it using your library, possibly just IntPtr.Zero.
    var ret = BBIA.CB_initNode(ref g_screen_node, 128, 128, EN_DevType.EN_C3Dev);

为了让我们自信地回答而不是猜测,请使用InitNode 的文档更新您的问题,并在致电InitNode 之前告诉我们您正在调用哪些函数(如果有)。

【讨论】:

  • 您好,感谢您的重播。你所有的建议都是正确的。但你的决心不起作用。在调用 InitNode 后的 c++ 中,*p_g_screen_node 更改并取一个值,但在 c# 中为 0x00000000。可能是为了对 IntPtr g_screen_node 变量的访问保护!!!
  • @MohammadFarahani - 答案已更新。但是,如果您希望我们更有信心地回答,请使用InitNode() 的文档更新您的问题。
【解决方案2】:

&g_screen_node 用于将g_screen_node 的地址传递给InitNode 函数。这通常意味着该参数将用作输出参数。

至于您收到错误代码的原因,我会说您对BBIA.CB_initNode 的呼叫需要&ab,而不是ab

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多