pinvoke - Calling c struct in C#. Cannot marshal field '***' of type '***' -


i c project named clib2cs 2 files clib2cs.c , clib2cs.h.

clib2cs.h following:

__declspec(dllexport) typedef struct btreenode {      int value;      struct btreenode* left;      struct btreenode* right;  }btnode;  __declspec(dllexport) unsigned long connectsession(unsigned long   handle,      unsigned char * publickey,      unsigned char   publickeylen);   __declspec(dllexport) void bulidtree(btnode* root, int value); 

clib2cs.c following:

#include "clib2cs.h" #include <stdio.h> #include <stdlib.h> unsigned unsigned long connectsession(unsigned long   handle,                                unsigned char * publickey,                                unsigned char   publickeylen) {          return 42; }   void bulidtree(btnode* root, int value) {     if (root == null) {        btnode* node = (btnode*)malloc(sizeof(btnode));        node->value = value;     }     if (value < root->value) bulidtree(root->left, value);     else bulidtree(root->right, value);  } 

this c project generates clib2cs.dll called in c-sharp project. c# project contains 1 file named program.cs.

progarm.cs following :

using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using system.runtime.interopservices;  namespace consoleapplication1 {     [structlayout(layoutkind.sequential)]     public class btnode {     public int value;     [marshalas(unmanagedtype.lpstruct)]     public btnode left;     [marshalas(unmanagedtype.lpstruct)]     public btnode right; }  class program {     [dllimport("clib2cs.dll", callingconvention = callingconvention.cdecl)]     unsafe static extern uint32 connectsession(uint32 handle, char* publickey, char publickeylen);      [dllimport("clib2cs.dll", charset = charset.auto)]     unsafe static extern void bulidtree([in, out, marshalas(unmanagedtype.lpstruct)] btnode root, int value);       public unsafe static uint32 getconnectsession(uint32 handle, string publickey, char publickeylen) {         // "convert" string char*         char* pubkey;         fixed (char* bptr = publickey) {             pubkey = (char*)bptr;         }         return connectsession(handle, pubkey, publickeylen);     }      static void main(string[] args)     {          uint32 ret =  getconnectsession((uint32)1, "helloworld", 'c');         console.writeline("####################: {0}", ret);          btnode root = new btnode();         root.value = 666;         console.writeline("value of root : {0}", root.value);          int[] vec = { 4, 5, 6, 7, 8, 9 };         foreach (int item in vec) {             bulidtree(root, item);         }          console.writeline("----------------------------------------------");         (; root != null; root = root.right) {             console.writeline("the tree node is: {0}", root.value);         }     } } } 

run it, , error:

unhandled exception:system.typeloadexception: cannot marshal field 'left' of type 'consoleapplication1.btnode': there no marshaling support type.

so, how invoke c struct of dll c# gracefully?

you're close.
suggest use string conversion.

string managedstring = marshal.ptrtostringansi((intptr) (char *) myunmanagedstring); 

you have know char* in c# , in c different char in c in 1 byte , in c# in 2 bytes pointer not same.

your question little generale.

  1. the first way marshall did in first attempt.

  2. the second way create cli c++ dll use library or dll code did in c project , because it's c++ it's easy use c code , c# both because of nature handle managed , unmanaged code result normal .net dll have add reference suggest take article more information:


Comments

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -