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.
the first way marshall did in first attempt.
the second way create
cli c++ dll
use library or dll code did inc
project , because it'sc++
it's easy usec
code ,c#
both because of nature handle managed , unmanaged code result normal.net dll
have add reference suggest take article more information:
Comments
Post a Comment