C#程序调用C++程序DLL遇到的坑
这两天有一个需求就是C++写的程序,给外包公司写界面,他们用的是C#写的,所以我得生成C++动态库(dll文件)给他们调用,过程中遇到了很多坑,这里记录下来给大家参考。
C#调用c++动态库(dll)方法
可以参考
总结一下就是先建一个C++程序,建立的时候选择dll类型。(或者右击项目-属性-常规-配置类型里将exe类型修改为dll类型)
然后建立一个头文件(test.h),一个c++文件(test.cpp)
test.h文件声明一个函数
extern "C" __declspec(dllexport) int add(int a, int b);
test.cpp文件写函数体,并导入test.h头文件
#include"test.h"
extern "C" __declspec(dllexport) int add(int a, int b){
return a+b;
};
然后右击项目,点击重新生成
并记录下生成dll的路径
然后创建一个c#程序用DllImport语句导入,路径是前面dll的路径
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
//这里注意,一个函数导入一次,如果是两个函数就导入两次,路径是前面生成的dll路径
[DllImport(@"D:\CC\Project7_源码版本_dll\Project7\Project7.dll", EntryPoint = "add")]
extern static int add(int a,int b);
static void Main(string[] args)
{
Console.WriteLine(add(2,3));
Console.ReadKey();
}
}
}
然后在main函数里进行测试,运行即可
当然,如果真有这么简单也没必要发这篇博客了,你可能会遇到各种各样的坑,让你绝望,下面列举我遇到过的坑。
问题1:报错System.DllNotFoundException
这个问题首先要检查生成的dll和C#运行的环境位数是不是一致的,要么都是32位,要么都是64位。
如果位数没问题,那就一定是你把dll移动到其他地方去了,dll在哪生成的就在哪放在,不要乱移动啊!!!在Debug目录下生成就Debug目录,在Release目录下生成就Release。DllImport写对应的路径就行了。
如果还是不行,建议看看其他的博客……反正博主这个问题没困扰多久就解决了
问题2:报错System.BadImageFormatException
这个,是我苦恼了两天的报错,一直没办法解决。最后没办法找了我室友c++大神帮忙解决了,就是下面这个一流软件架构师。
主要问题还是位数的问题,程序调用了位数不一致的库。
解决方案1:生成和调试都用32位的。
解决方案2:如果你就是想用64位的,那就右击C#程序-属性-生成-目标平台改为x64(或者Any CPU,取消勾选首选32位)
就是这个问题,你觉得自己明明选择了x64运行,可它其实还是默认32位运行的。
如果只要调用加法的测试函数,基本上就只会碰到上面两个问题。如果你想调用自己的程序,你可能会遇到下面这些问题
问题3:参数有字符串,报错System.AccessViolationException
废话不多说,直接上解决方案:
cpp文件参数类型写char*,在函数体里面可以直接把char* 类型赋值给string类型,但是参数必须是char*类型
extern "C" __declspec(dllexport) int add(char* str);
c#程序参数写string
[DllImport(@"D:\\test.dll", EntryPoint = "add")]
extern static int add(string str);
还有一种可能会报错System.AccessViolationException,就是函数不对应,我有次是 EntryPoint = "add"这个忘记改成对应的函数名了,也是报的这个错,所以仔细检查,把函数名对应起来。
问题4:如何返回多个值
好像有种方法是返回结构体,但我尝试了一下没成功就用了另一种办法,一下就成功了。
那就是,传地址:
cpp文件参数类型写地址int*
extern "C" __declspec(dllexport) int add(int* a,int* b){
a++;
b++;
return a;
};
c#程序参数写ref int
[DllImport(@"D:\\test.dll", EntryPoint = "add")]
extern static int add(ref int a,ref int b);
static void Main(string[] args)
{
//这里必须先初始化
int a=0;
int b=0;
Console.WriteLine(add(ref a,ref b));
Console.WriteLine(a);
Console.WriteLine(b);
Console.ReadKey();
}
转载:https://blog.csdn.net/qq_41967982/article/details/114450427