我得到了一个名为Clib2CS的c项目,它有两个文件,分别是Clib2CS.c和Clib2CS.h。
Clib2CS.h如下:
__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如下:
#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);
}
这个c项目生成一个Clib2CS.dll,它将在一个c-sharp项目中调用。 c#项目只包含一个名为Program.cs的文件。
Progarm.cs如下:
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 to 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 is : {0}", root.value);
int[] vec = { 4, 5, 6, 7, 8, 9 };
foreach (int item in vec) {
bulidTree(root, item);
}
Console.WriteLine("----------------------------------------------");
for (; root != null; root = root.right) {
Console.WriteLine("the tree node is: {0}", root.value);
}
}
}
}
运行它,我收到此错误:
未处理的异常:System.TypeLoadException:无法编组字段'left' 键入'ConsoleApplication1.BTnode':此类型没有编组支持。
那么,我们如何从c#优雅地调用DLL的c结构?
答案 0 :(得分:0)
你太近了 我建议你用它来进行字符串转换。
String managedString = Marshal.PtrToStringAnsi((IntPtr) (char *) myUnmanagedString);
您必须知道char*
和c#
中的c
不同,c
中的字符位于1个字节中,而c#
中的字符位于2个字节中所以指针不一样。
你的问题有点小。
第一种方法是像第一次尝试那样进行编组。
第二种方法是创建CLI C++ DLL
使用您的库或DLL代码,就像在此C
项目中一样,因为它是C++
所以它很容易使用您的C
代码和C#
两者都是因为其处理托管代码和非托管代码的性质,因此它会像普通的.net dll
一样只需将其添加为引用,这样我就可以了建议查看本文以获取更多信息: