0
votes

i have c++ type definition like this

typedef void* ScreenNode;

and use it in my c++ code like this

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

**EN_C1Dev is a ENUM

my typedef variable is a void pointer and InitNode return a value by changing pointer value "g_screen_node".

now i use this function in a dll inside a C# program with this definition

c++ code

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 definition class

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

and finally my main program

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

the CB_initNode function return error code and g_screen_node not return Expected value and stay on 0x00000000!

2
Don't use pointers in C# unless you have to. (Hint: You don't have to. Change the P/Invoke signature to use ref int g_screen_node instead and pass ref ab. This will not fix your error, but it's still something you should change.)cdhowie

2 Answers

0
votes

Answering the parts of your question in order:

  1. You should consult the documentation (or source code, if no documentation is available) of InitNode for the meanings of the input and output arguments of InitNode. Most likely the method actually allocates and initializes a ScreenNode and returns an opaque pointer to the caller -- one whose internal implementation is hidden. However, there is not enough information in your question to determine this for certain.

    My answers to the remaining parts of your question assume that this is true. If not, please update your question with appropriate documentation from InitNode, then we can take another cut at answering.

  2. c++ code. You need to decorate your function with 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;
    }
    

    You also need to pass in a pointer to a ScreenNode (i.e. a double pointer) so that the pointer value set in InitNode() can be communicated out.

  3. And then in your c# extern declaration, you define the returned pointer as an 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. Then in the main program:

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

Then later, if you need to pass a ScreenNode back to the same library, you would use the IntPtr previously returned. And when done with it, don't forget to free it -- presumably the library you are using has a method for that also.

Finally, you don't state what EN_DevType is, but I am guessing that it is an enum. If so, you should check you have the correct values. If not an enum, then my answer to your question might need to be updated.

Update

If InitNode needs to know the current value of the incoming void ** pointer because it is preallocated or preinitialized, the signatures would be as follows:

    [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);

In order for us to answer in confidence rather than guessing, please update your question with the documentation for InitNode, and let us know what functions you are calling before the call to InitNode, if any.

0
votes

&g_screen_node is used to pass the address of g_screen_node to the InitNode function. This is usually means the parameter will be used as an output parameter.

As to why you're getting an error code, I'll take a stab and say your call to BBIA.CB_initNode needs &ab, not ab