C#程序調(diào)用C++動(dòng)態(tài)庫(dll文件)遇到的坑及解決
C#程序調(diào)用C++程序DLL遇到的坑
這兩天有一個(gè)需求就是C++寫的程序,給外包公司寫界面,他們用的是C#寫的,所以我得生成C++動(dòng)態(tài)庫(dll文件)給他們調(diào)用,過程中遇到了很多坑
這里記錄下來給大家參考。
C#調(diào)用c++動(dòng)態(tài)庫(dll)方法
可以參考:C#調(diào)用C++的dll兩種實(shí)現(xiàn)(托管與非托管)
總結(jié)一下就是先建一個(gè)C++程序,建立的時(shí)候選擇dll類型。(或者右擊項(xiàng)目-屬性-常規(guī)-配置類型里將exe類型修改為dll類型)


然后建立一個(gè)頭文件(test.h),一個(gè)c++文件(test.cpp)
test.h文件聲明一個(gè)函數(shù)
extern "C" __declspec(dllexport) int add(int a, int b);
test.cpp文件寫函數(shù)體,并導(dǎo)入test.h頭文件
#include"test.h"
extern "C" __declspec(dllexport) int add(int a, int b){
return a+b;
};然后右擊項(xiàng)目,點(diǎn)擊重新生成

并記錄下生成dll的路徑

然后創(chuàng)建一個(gè)c#程序用DllImport語句導(dǎo)入,路徑是前面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
{
//這里注意,一個(gè)函數(shù)導(dǎo)入一次,如果是兩個(gè)函數(shù)就導(dǎo)入兩次,路徑是前面生成的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函數(shù)里進(jìn)行測試,運(yùn)行即可

當(dāng)然,如果真有這么簡單也沒必要發(fā)這篇博客了,你可能會(huì)遇到各種各樣的坑,讓你絕望,下面列舉我遇到過的坑。
問題1:報(bào)錯(cuò)System.DllNotFoundException
這個(gè)問題首先要檢查生成的dll和C#運(yùn)行的環(huán)境位數(shù)是不是一致的,要么都是32位,要么都是64位。
如果位數(shù)沒問題,那就一定是你把dll移動(dòng)到其他地方去了,dll在哪生成的就在哪放在,不要亂移動(dòng)?。。?!
在Debug目錄下生成就Debug目錄,在Release目錄下生成就Release。DllImport寫對(duì)應(yīng)的路徑就行了。
如果還是不行,建議看看其他的博客……反正博主這個(gè)問題沒困擾多久就解決了
問題2:報(bào)錯(cuò)System.BadImageFormatException
這個(gè),是我苦惱了兩天的報(bào)錯(cuò),一直沒辦法解決。最后沒辦法找了我室友c++大神幫忙解決了,就是下面這個(gè)一流軟件架構(gòu)師。

主要問題還是位數(shù)的問題,程序調(diào)用了位數(shù)不一致的庫。
解決方案1:
生成和調(diào)試都用32位的。
解決方案2:
如果你就是想用64位的,那就右擊C#程序-屬性-生成-目標(biāo)平臺(tái)改為x64(或者Any CPU,取消勾選首選32位)


就是這個(gè)問題,你覺得自己明明選擇了x64運(yùn)行,可它其實(shí)還是默認(rèn)32位運(yùn)行的。
如果只要調(diào)用加法的測試函數(shù),基本上就只會(huì)碰到上面兩個(gè)問題。如果你想調(diào)用自己的程序,你可能會(huì)遇到下面這些問題
問題3:參數(shù)有字符串,報(bào)錯(cuò)System.AccessViolationException
廢話不多說,直接上解決方案:
cpp文件參數(shù)類型寫char*,在函數(shù)體里面可以直接把char* 類型賦值給string類型,但是參數(shù)必須是char*類型
extern "C" __declspec(dllexport) int add(char* str);
c#程序參數(shù)寫string
[DllImport(@"D:\\test.dll", EntryPoint = "add")] extern static int add(string str);
還有一種可能會(huì)報(bào)錯(cuò)System.AccessViolationException,就是函數(shù)不對(duì)應(yīng),我有次是 EntryPoint = "add"這個(gè)忘記改成對(duì)應(yīng)的函數(shù)名了,也是報(bào)的這個(gè)錯(cuò),所以仔細(xì)檢查,把函數(shù)名對(duì)應(yīng)起來。
問題4:如何返回多個(gè)值
好像有種方法是返回結(jié)構(gòu)體,但我嘗試了一下沒成功就用了另一種辦法,一下就成功了。
那就是,傳地址:
cpp文件參數(shù)類型寫地址int*
extern "C" __declspec(dllexport) int add(int* a,int* b){
a++;
b++;
return a;
};c#程序參數(shù)寫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();
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- C# 調(diào)用C++寫的dll的實(shí)現(xiàn)方法
- C++調(diào)用C#的DLL實(shí)現(xiàn)方法
- C#調(diào)用C++dll方法步驟
- C++與C#互調(diào)dll的實(shí)現(xiàn)步驟
- C#調(diào)用C++DLL傳遞結(jié)構(gòu)體數(shù)組的終極解決方案
- C++調(diào)用C#的DLL程序?qū)崿F(xiàn)方法
- c#調(diào)用c++的DLL的實(shí)現(xiàn)方法
- 基于C#調(diào)用c++Dll結(jié)構(gòu)體數(shù)組指針的問題詳解
- C#程序如何調(diào)用C++?dll詳細(xì)教程
- C++項(xiàng)目中調(diào)用C#DLL的三種方式
相關(guān)文章
教你創(chuàng)建一個(gè)帶診斷工具的.NET鏡像
本文編寫的初衷是因?yàn)樵谌豪镉泻芏嘈』锇橛龅缴a(chǎn)環(huán)境性能問題的時(shí)候,.NET的runtime鏡像中沒有帶一些工具,安裝和使用起來很麻煩,所以分享一些我們公司內(nèi)部一些技巧,對(duì).NET鏡像帶診斷工具相關(guān)知識(shí)感興趣的朋友一起看看吧2022-07-07
C#連接db2數(shù)據(jù)庫的實(shí)現(xiàn)方法
本篇文章是對(duì)C#連接db2數(shù)據(jù)庫的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
一款域名監(jiān)控小工具 Domain(IP)Watcher 實(shí)現(xiàn)代碼
域名是否正常,網(wǎng)站是否可以正常訪問是很頭痛的問題,怎樣簡單地監(jiān)控域名是否可以正常訪問呢,這里發(fā)布一款域名監(jiān)控小工具:Domain(IP)Watcher2011-11-11
C#操作mysql數(shù)據(jù)庫的代碼實(shí)例
這篇文章為大家提供了一個(gè)C#操作mysql數(shù)據(jù)庫的實(shí)例,大家可以參考使用2013-11-11
Unity ScrollRect實(shí)現(xiàn)軌跡滑動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Unity ScrollRect實(shí)現(xiàn)軌跡滑動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09

