最近项目需要用差分升级,固件打包工具是用C#写的,差分包生成软件是用C++ MFC写的。
为了方便使用,打算把C++部分做成DLL,用C#调用,减少软件数量,也方便操作。
一、C++程序做成DLL
1.重新创建C++ DLL工程
原本打算让MFC程序直接生成DLL,即生成的时候,同时生成MFC软件和DLL。DLL可以供C#调用;MFC软件也可以单独使用,用于生成差分包。
结果做不到,于是老老实实按网上教程,重新创建C++ DLL工程,然后把程序和文件夹都复制过去。
2.修改代码
我设计的是C#把“原固件”、“新固件”和“差分包”的文件名绝对地址,传给DLL。在DLL中执行打开文件、写入数据的操作。
因此,程序改动需要把原程序中MFC部分都删掉,文件操作改成了:fopen_s、fread、fclose等函数。
3.DLL中添加必要的结构
在头文件中添加:
#pragma once
extern "C" __declspec(dllexport) int xxxxxx(char *patchfile_dll, char *oldfile_dll, char *newfile_dll, char *patchfile_in_dll);
注意:需要添加extern "C",否则生成的DLL中函数名会被改得乱七八糟。
在.cpp文件程序前面添加:
using namespace std;
另外,使用了strcpy_s,需要
#include <string>
4.C#中添加必要的结构
①添加:
[DllImport("XXXXX.dll")]
②声明被调用的函数
③发给DLL的文件名格式是:string。
如果想从DLL收到返回的文件名,在C#中定义
StringBuilder patchfile_dll = new StringBuilder(100);
然后把patchfile_dll 这个变量也发送过去。
在DLL中,文件名全部用char *指针接收。
二、发生过的错误
1.需要添加extern "C",否则生成的DLL中函数名会被改得乱七八糟,C#程序找不到该函数。
2.需要返回的文件名,不能用string定义,需要StringBuilder patchfile_dll = new StringBuilder(100)。
3.DLL采用静态链接,运行库改成MTd,否则别人的电脑可能不能正常调用DLL,会提示找不到DLL。这个错误搞了好久,最后去搜索:怎么让DLL不用其他库支持,才解决。
错误提示如下:
System.DllNotFoundException: 无法加载 DLL“XXXXX.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E)。
4.DLL工程要根据别人的电脑选X86或X64,否则别人电脑可能不能正常调用DLL
5.C#工程要根据别人电脑选择合适的框架,否则别人电脑可能打不开。想从微软下个.NET3.5框架,800年都下不下来,全网资源没一个装上后,让软件停止继续索求框架。