【大型软件开发】开发日志(五).net框架与C++的融合:CLR——C++调用C#的DLL
做什么?
先说一下场景,现在正在开发一个Qt ActiveServer,也就是用一个应用程序去向其他的组件暴露接口,以达到提供服务的目的。
然后新版的框架要提供大部分功能,也就是要重做大部分模块。现在有一个问题,就是有一个用于提供向web发送post请求,获得回执并解析的模块,叫LBD_WebApiInterface
然后现在,我要将这个模块整合到新的Qt ActiveServer里面去,做这个的时候我踩了巨多的坑,做了差不多快一个星期才勉强搞清楚这个怎么做。
其实是很简单的,但是它并不会告诉你错在哪,你只能自己猜谜,这点是最头疼的。
其次,如果有可能,如果是在Windows环境下,我是及其推荐你把C#的DLL改装成COM组件,并注册进系统内,这样可以省去非常非常多的麻烦,不会以至于你在开发的时候跨过和我一样多的坑。
然后我发现CLR这一块完全是一片空白,国内基本上找不到什么中文资料和讨论,真要被这玩意搞得头晕了。
怎么做?
首先我们要知道CLR是什么,知道的 就知道了,不知道的你也只能自己去百度了。
实际上,CLR语言就是个C#语言和C++语言的结合体,具体语法我这里不会过多阐述,只说应用
因为我这里大部分的类都是以单例的形式对外暴露的,具体是否需要使用单例可以视情况而定,总之我这里就要用单例:
注:其中这个LBD_WebApiInterface的namespace就是来自我需要调用的那个C#的DLL
这个类里面我只是需要获得一个单例,返回我们在这个CLR项目中,由C#DLL生成的单例,仅此而已。
甚至不需要一个类去包裹,当然了最好还是有一个类去管理gc,不然我也不知道会发生什么。
然后就是写接口了,写一个DLL 对外暴露的类:TeachInfo
这个宏的目的是为了复用这个头文件,这样就可以在调用方直接引用这个头文件而不需要修改了
如果想要这个宏正常工作的话,则需要源文件在调用这个头文件的上方加入宏定义
#ifndef _IWEB_H
#define _IWEB_H
// 通过宏来控制是导入还是导出
#ifdef _IWEB
#define WEB_API __declspec(dllexport)
#else
#define WEB_API __declspec(dllimport)
#endif
//..代码块
#endif
先来看下转换数据类型的头文件Trans.h
因为System::Sring类型相当于是托管类型,不能直接转换成std::string,所以必须要听过msclr\marshal_cppstd.h里面提供的这个marshal_as函数进行转换
这里有一个比较坑的点,就是你必须要把这个
#include <msclr/gcroot.h> //gcroot
#include <msclr\marshal_cppstd.h>
这两行 放在
using namespace msclr::interop;
的前面,否则会报错:
"*"不能再类型"IServiceProvider"上使用此间接寻址。
除此之外
#include "windows.h"
这一行的引用和上述引用的位置也可能导致类似的问题,这里就不细说了
然后我们来看一个简单的示例
注:CLR类型需要在源文件的开头引用
#include "pch.h"
头文件,这个头文件将决定哪些内容会被编译,如果你不包含这个头文件的话就不会编译了,然后就有可能报错LNK2019
然后就是,除了头文件之外,你的源文件中的每一个函数都需要一个WEB_API的标记,否则调用方可能会报错LNK2019
来看下调用方
调用方的话 其实也比较简单,我之前犯了一个错误害得我搞了好久,都没能解决问题
首先需要知道的一点是,#pragma comment(lib,"xxx.lib")这条宏和你在vs中对项目的设定是不一样的,如果你在VS中设定的比如链接库地址,但是你#pragma comment(lib,"xxx.lib")的位置是错误的,编译器会优先尝试导入你写的这条宏,这会导致
LNK 2019
然后还有一点就是,你是可以用#pragma comment(lib,"xxx.lib")引用这个lib文件,但是如果这个lib依赖的库不在应用程序的根文件夹下,有可能这个应用程序编译之后会有两个问题
1.LNK2019
2.ActiveServer 注册失败
我只提供一个范例,具体问题我不再分析
最新文章
- 【腾讯Bugly经验分享】程序员的成长离不开哪些软技能?
- 自定义指令-directive (转)
- 孙鑫MFC学习笔记12:文件读写
- AES加密解密
- SlickGrid example 1: 最简单的例子和用法
- ERROR 1005 (HY000): Can&#39;t create table&#39;matrix.system_log&#39; (errno: 150)
- [LeetCode] Find Duplicate File in System 在系统中寻找重复文件
- Android ToggleButton 实践
- 【网站搭建】搭建独立域名博客 -- 独立域名博客上线了 www.hanshuliang.com
- laravel 5.4中手动创建分页
- [四] java8 函数式编程 收集器浅析 收集器Collector常用方法 运行原理 内部实现
- 6.4 SpringData JPA的使用
- 【转】Android hdpi ldpi mdpi xhdpi xxhdpi适配详解
- kettle 6.1 日志查询
- matplotlib绘图不显示问题解决plt.show()
- iOS开发中didSelectRowAtIndexPath tap事件响应延迟
- 通过JDOM实现XML与String的相互转换
- CF 468B Two Sets
- POJ 3233 Matrix Power Series(二分等比求和)
- no matching editors or conversion strategy found
热门文章
- 学习ASP.NET Core Blazor编程系列十六——排序
- linux系统部署微服务项目
- 【转载】SQL Server FileStream 体验
- [python] 向量检索库Faiss使用指北
- 微服务框架——MybatisPlus
- 又一重要进展发布!OpenMMLab算法仓支持昇腾AI训练加速
- ChatGPT/InstructGPT详解
- three.js一步一步来--如何画出一个逃跑的圆柱体
- angular使用_HttpClient或者Fetch发送POST/GET请求下载/上传文件
- 【分析笔记】全志方案通过命令行操作 GPIO 口(带源码分析)