用C#掉用C++的dll直接import就可以之前有不同的类型对应,当要传递结构体的时候就有点麻烦了,这里有一个结构体里边有char*类型,这个类型在C#中调用没法声明,传string是不行的默认string是对应const char*,传stringbuilder得指定大小,不然是没法传的,
查了好久,最后只能用unsafe代码来实现了
用C/C++写一个标准的动态链接库:
头文件,定义了三个接口函数,
#pragma once #define TESTDLL _declspec(dllexport) #ifndef PKI_DATA_ST #define PKI_DATA_ST typedef struct PKI_DATA_st { int size; char *value; }PKI_DATA, *PKI_PDATA; #endif extern "C" { TESTDLL double Add(double a, double b); TESTDLL double Subtract(double a, double b); TESTDLL int TestDn(PKI_DATA cert, PKI_DATA* dn); }
简单实现:
#include "stdafx.h" #include "TestClass.h" double Add(double a, double b) { printf("Add "); return a + b; } double Subtract(double a, double b) { printf("Subtract"); return a - b; } int TestDn(PKI_DATA cert, PKI_DATA* dn) { printf("TestDn cert.value: %s ", cert.value); dn->size = 10; //dn->value = "helloworld"; //这个种写法需要转换 dn->value =(char*) TEXT("helloworld");//这种写法在选择unicode字符集时C#是可以直接接受的 return 1; }
C#调用,路径可以用当前程序的相对路径,也可以是系统的环境变量中的路径,声明import
[DllImport("USBLoad.dll", EntryPoint = "Add", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] static extern double Add(double a,double b); [DllImport("USBLoad.dll", EntryPoint = "TestDn", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] static extern int TestDn(PKI_DATA cert, ref PKI_DATA dn); [DllImport("USBLoad.dll", EntryPoint = "Subtract", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] static extern double Subtract(double a, double b);
声明结构体:
internal unsafe struct PKI_DATA { internal int size; internal char* value; }
调用:记得属性中勾上允许不安全代码
[HandleProcessCorruptedStateExceptions]//这个可以捕获C++中的异常
[SecurityCritical] static unsafe void TestUSBLoad()//加unsafe { try { var a = Add(10, 10); w(a); a = Subtract(15, 10); w(a); PKI_DATA cert = new PKI_DATA(); cert.size = 4; char[] test = "test".ToCharArray(); string s = ""; fixed (char * v=test)//传值初始化。需要fixed关键字 { cert.value = v; PKI_DATA dn = new PKI_DATA(); TestDn(cert, ref dn); var encode = Encoding.ASCII; var c = dn.value; List<char> list = new List<char>(); for (int i=0;i<dn.size;++i,++c) { list.Add(*c); }
//兼容ansi编码,先转byte var bytes = Encoding.Unicode.GetBytes(list.ToArray()); s = Encoding.ASCII.GetString(bytes);//转码 w(new string(dn.value));//设置unicode字符集的情况下可以直接这么写就能得到要字符 } s = s.Replace("