用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 \n");
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\n", cert.value);
dn->size = ;
//dn->value = "helloworld"; //这个种写法需要转换
dn->value =(char*) TEXT("helloworld");//这种写法在选择unicode字符集时C#是可以直接接受的
return ;
}

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(, );
w(a);
a = Subtract(, );
w(a); PKI_DATA cert = new PKI_DATA();
cert.size = ;
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=;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("\0","");//转码的时候后边会有很多\0,移除
w(string.Format("[{0}]",s)); }
catch (Exception ex)
{
w(ex.Message);
} }

顺便研究了下C++的动态调用、

如果是静态调用需要头文件和lib库,直接引用头文件,加入lib的链接路径,引用后可以直接用,编译就可以了

动态调用用loadlibrary,记得freelibrary,这些函数在windows.h中,这里建的是QT的项目所以引用的是qt_windows.h:

#include "qt_windows.h"

#define DLLPATH  (LPCTSTR)"USBLoad.dll"

#ifndef PKI_DATA_ST
#define PKI_DATA_ST
typedef struct PKI_DATA_st {
int size;
char *value;
}PKI_DATA, *PKI_PDATA;
#endif //声明入口函数
typedef double(*Add_Func)(double, double); typedef int(*TestDn)(PKI_DATA, PKI_DATA*); int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv); qDebug() << "hello world!";
HINSTANCE m_hModule = LoadLibrary(DLLPATH);//加载dll
if (m_hModule == NULL)
{
printf("LoadLibrary %s failed,err %d\n", DLLPATH, GetLastError());
goto END;
}
Add_Func add;
add = (Add_Func)GetProcAddress(m_hModule,"Add");//获取方法地址,后边调用
double c = add(, );
printf("Add_Func: %lf \n", c);
TestDn test;
test = (TestDn)GetProcAddress(m_hModule, "TestDn");
PKI_DATA cert;
PKI_DATA dn;
cert.size = ;
cert.value = (char*)"test";
int res = test(cert, &dn);
printf("TestDn:%s\n", dn.value); END:
if (m_hModule != NULL)
{
FreeLibrary(m_hModule);
m_hModule = NULL;
printf("FreeLibrary\n");
}
return a.exec();
}

关于怎么把char*转码到正确的编码格式下的C#string,

 char* cchar=data
IntPtr value = new IntPtr(cchar);
var s = Marshal.PtrToStringAnsi(value);

可以用上边的方法,看fcl的源码可以看到上边的方法实质是把char*强转为sbyte*,然后直接new string,这样可以避免C++和C#的byte差异

marshal还有touni的方法,只转unicode的方法,实质是直接用char* new string,

char*和sbyte*两种初始化参数string类型都接受。

C# 调用C/C++动态链接库,结构体中的char*类型的更多相关文章

  1. C/C++中指向结构体变量的指针,调用指向的那个结构体中的成员

    设p是指向结构体变量的指针,则可以通过以下的方式,调用指向的那个结构体中的成员: (1)结构体变量.成员名.如,stu.num. (2)(*p).成员名.如,(*p).num. (3)p->成员 ...

  2. C语言 结构体中的零长度数组

    /* C语言零长度数组大小和取值问题 */ #include <stdio.h> #include <stdlib.h> #include <string.h> s ...

  3. C结构体中数据的内存对齐问题

    转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...

  4. C#调用C++ dll时,结构体引用传参的方法

    写了一个C++的LogLog Logit 四参数等算法的接口dll,给C#调用,但是发现传参有问题 如 extern "C" _declspec(dllexport)  bool ...

  5. C#调用C++DLL传递结构体数组的终极解决方案

    在项目开发时,要调用C++封装的DLL,普通的类型C#上一般都对应,只要用DllImport传入从DLL中引入函数就可以了.但是当传递的是结构体.结构体数组或者结构体指针的时候,就会发现C#上没有类型 ...

  6. 绝对好文C#调用C++DLL传递结构体数组的终极解决方案

    C#调用C++DLL传递结构体数组的终极解决方案 时间 2013-09-17 18:40:56 CSDN博客相似文章 (0) 原文  http://blog.csdn.net/xxdddail/art ...

  7. C++结构体中sizeof(1)

    sizeof sizeof操作符的作用是返回一个对象或类型名的长度,长度的单位是字节. 返回值的类型是标准库命名为size_t的类型,size_t类型定义在cstddef头文件中,该头文件是C标准库的 ...

  8. C语言中free()函数释放struct结构体中的规律

    并不是什么新鲜的事情,不过值得注意.首先我们知道,在使用struct来定义并声明一个变量时,将会自动划分出一个连续的储存空间(虽然根据某些对齐原则会出现内存间隙,但是大体上来说还是连续的)这一块连续空 ...

  9. golang 结构体中的匿名接口

    golang 结构体中的匿名接口 代码示例 golang 中,可以给结构体增加匿名field,可参考 unknwon 大神的书. 匿名字段和内嵌结构体 但,golang同时也可以给结构体定义一个匿名i ...

随机推荐

  1. 记一次优化ansible inventory的小例子

    起因: 阿里云新扩容一批机器,要对上面的flume配置做修改 之前的inventory是这样子的 [user@vip10-ali-tj-console host_vars]$ sdiff vip10- ...

  2. mysql 查看索引

    查看索引 mysql> show index from tblname; mysql> show keys from tblname; · Table 表的名称. · Non_unique ...

  3. Haproxy搭建Web群集

    一.Haproxy与LVS LVS不支持正则处理,不能实现动静分离,对于大型网站,LVS的实施配置复杂,维护成本相对较高 Harpoxy是一款可提供高可用性,负载均衡.及基于TCP和HTTP应用的代理 ...

  4. iOS开发~制作同时支持armv7,armv7s,arm64,i386,x86_64的静态库.a以及 FrameWork 的创建

    armv7,armv7s,arm64,i386,x86_64 详解 一.概要 平时项目开发中,可能使用第三方提供的静态库.a,如果.a提供方技术不成熟,使用的时候就会出现问题,例如: 在真机上编译报错 ...

  5. 50.RocketMQ (quickstart)

    要多给下属表功,绝不能抢功. 1.订阅消息 /** * Copyright (C) 2010-2013 Alibaba Group Holding Limited * * Licensed under ...

  6. QuantLib 金融计算——基本组件之 DayCounter 类

    目录 QuantLib 金融计算--基本组件之 DayCounter 类 DayCounter 对象的构造 一些常用的成员函数 如果未做特别说明,文中的程序都是 Python3 代码. QuantLi ...

  7. 【old】Python学习笔记

    上学期看视频记得,也没学到多少,目前打算一边通过<Python学习手册 第四版>提高核心语法(太厚了 噗),一边学习Python Web开发 然后这里的多任务编程和网络编程是暑假学的 5. ...

  8. 图解http 笔记

    一,了解web以及网络基础 1,使用http协议访问web web页面是由web浏览器根据地址栏中指定的url从web服务器获取文件资源等信息然后显示的页面. 像这种通过发送请求获取服务器资源的web ...

  9. IIS7如何实现访问HTTP跳转到HTTPS访问 转的

    加几句,1.安装url重写模块,不需要重启IIS,安装完了就能用.个人感觉比 IIS REWRITE组件更好用,iis rewrite是安装第三方的那种,不缴费只可以把所有规则写在一起,不能区别站点, ...

  10. Mac下配置idea(Mac 10.12)

    idea应该是第二个最好用的开发工具,除了宇宙最强大的VS第一外,过来就是它,其体系中已经发布很多语言的开发工具. idea:http://bbs.feng.com/read-htm-tid-1050 ...