国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C#調(diào)用C++動態(tài)庫

這篇具有很好參考價值的文章主要介紹了C#調(diào)用C++動態(tài)庫。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

一、序言

在C#開發(fā)過程中,我們可能會遇到需要調(diào)用Windows API 或是第三方庫的場景,然而有時候這些庫是由C++編寫的,并不能直接應(yīng)用在C#的程序中,這為開發(fā)帶來許多阻力。本文介紹兩種使用C#調(diào)用C++動態(tài)庫的方式,以及在這個過程中可能遇到的問題,看完之后會對你的困境有所幫助。

二、非托管與托管

很多時候在項目中需要通過C++調(diào)用C#的dll,或者反過來調(diào)用。首先明白一個前提:C#是托管型代碼。C++是非托管型代碼。簡而言之:

  • 托管型代碼的對象在托管堆上分配內(nèi)存,創(chuàng)建的對象由虛擬機(jī)托管。(C# )
  • 非托管型代碼對象有實(shí)際的內(nèi)存地址,創(chuàng)建的對象必須自己來管理和釋放。(C++)

所以C#調(diào)用C++的動態(tài)庫可以歸類成兩種辦法:

  1. 非托管C++創(chuàng)建的dll庫,需要用靜態(tài)方法調(diào)用;
  2. 直接使用CLR,生成托管C++dll庫。

接下來詳細(xì)介紹具體的實(shí)現(xiàn)方式。

三、方法一:靜態(tài)調(diào)用

1.加載第三方動態(tài)庫

在使用C#時,在解決一些問題時會用到Windows API,這時你很容易看到如下的調(diào)用:


[DllImport("user32.dll")]
public static extern bool ReleaseCapture();

[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (e.Button == MouseButtons.Left)
            {
                ReleaseCapture();
                SendMessage(Handle, 0x00A1, 2, 0);
            }
        }

這就是通過DLLImport來靜態(tài)調(diào)用動態(tài)庫中的方法,比較便捷,適用于一些簡單的調(diào)用,但是缺點(diǎn)也很明顯,想要使用相應(yīng)的方法就得提前進(jìn)行靜態(tài)聲明,而且不利于參數(shù)傳遞,也就是說如果參數(shù)有在庫中聲明的結(jié)構(gòu)體,不能直接被靜態(tài)方式引用,你必須在庫中聲明一個公共類做為接口來暴露數(shù)據(jù)。而有時我們使用的DLL是第三方的工具,不方便自己開源修改。

2.自定義動態(tài)庫

有時候我們需要自己編寫動態(tài)庫來調(diào)用,就可以參考如下形式:

例子:新建C++項目,創(chuàng)建動態(tài)鏈接庫(DLL),然后添加頭文件textdll.h

#pragma once
#ifdef A_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif

extern "C" DLL_API void MessageBoxShow();   //通過extern “C” 使MessageBoxShow方法為一個導(dǎo)出方法,外部可見

這一步是要在頭文件中聲明接口,之后需要實(shí)現(xiàn)相應(yīng)的函數(shù):

#include "stdafx.h"
#include "textdll.h"
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

void MessageBoxShow()
{
    MessageBox(NULL, TEXT("Hello World"), TEXT("In a DLL"), MB_OK);
}

我們編譯之后,在目錄下會生成 一個DLL(.dll為后綴的文件),我們復(fù)制到C#的debug目錄下,使用C#程序靜態(tài)調(diào)用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;  //必須要添加該引用
using System.Text;
using System.Threading.Tasks;

namespace dlltest
{
    class Program
    {
        [DllImport("TESTDLL.dll")]  //最關(guān)鍵的,導(dǎo)入該dll
        public extern static void MessageBoxShow();

        static void Main(string[] args)
        {
            MessageBoxShow();
        }
    }
}

但是這樣做在很多時候不太方便,如果想要知道庫中具體有哪些函數(shù),還需要去翻閱文檔或者源碼,調(diào)用前還需要逐個進(jìn)行靜態(tài)的聲明,所以接下來引用第二種方法。

四、方法二:托管C++動態(tài)庫

通過C++/CLI作為中間層,因為C++/CLI既可調(diào)用.NET的類庫,又可調(diào)用C++原生庫,

所以可以通過C# 調(diào)用 C++/CLI 再調(diào)用 C++ DLL這樣的三層調(diào)用方式完成。

1.動態(tài)庫

首先需要編寫一個DLL,可以是自己編寫的動態(tài)庫也可以是第三方的動態(tài)庫,但是很重要一點(diǎn)是,在函數(shù)中需要有如下聲明才能被后續(xù)引用:


_declspec(dllexport) int sum(int a, int b);//給c++調(diào)用
 
extern "C" __declspec(dllexport) int sum(int a, int b);//給c#調(diào)用

如果是自己編譯則在VS中選擇創(chuàng)建DLL項目,如何編寫動態(tài)庫這里就不贅述:

c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言

2.新建CLR項目

1.創(chuàng)建

打開VS,創(chuàng)建一個CLR的空項目:

c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言
從描述中就可以看到CLR本身就是打通.NET與C++代碼的橋梁。

2.配置

以實(shí)現(xiàn)HID相關(guān)的USB功能為例,需要使用到一個hid的動態(tài)庫,在創(chuàng)建完項目后打開項目屬性,先引用第三方的DLL:
c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言

這個庫目錄中需要包含同名的相關(guān)文件:
c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言

同時引用庫:
c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言
3.方法
然后新建一個類文件來編寫相關(guān)方法:
Cli.h

#pragma once
#include "hidapi.h"

public ref class DFUCli
{
public:
	hid_device* handle;

	DFUCli();

	int Openhid();

	void test();

};

Cli.cpp

#include "DFUCli.h"

DFUCli::DFUCli()
{
}

int DFUCli::Openhid()
{
	uint16_t pid = 0x0000;
	uint16_t vid = 0x0000;
	
	handle = hid_open(vid, pid, NULL);
	if (handle == NULL) {
		return -1;
	}
	return 0;
}

void DFUCli::test()
 {
}

編寫完成之后進(jìn)行編譯,此處需要更改生成類型為動態(tài)庫:
c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言
這樣我們就得到一個CLR的動態(tài)庫文件。

3.C#引用DLL間接調(diào)用方法

新建一個C#工程,引用剛剛生成的DLL:
c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言
這時我們就能像使用普通的動態(tài)庫一樣調(diào)用相關(guān)方法,實(shí)例化對象之后,VS還會自動提示相應(yīng)的函數(shù),無須其他多余操作:
c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言

五、問題點(diǎn)匯總

當(dāng)然由于這種多級的調(diào)用,經(jīng)常會由于錯誤的操作或者配置導(dǎo)致一些未知的錯誤,下面整理了一些調(diào)試過程中遇到的問題,可能對你有所幫助:

1.fatal error LNK1561: 必須定義入口點(diǎn)

出現(xiàn)這個錯誤是由于我們創(chuàng)建的DLL是并沒有入口函數(shù),也就是main函數(shù),而編譯器按常規(guī)流程處理引發(fā)錯誤,有兩種解決方式。

(1)設(shè)置子系統(tǒng),解決方案上,右鍵->屬性->鏈接器->系統(tǒng)->子系統(tǒng),下拉框選擇:窗口 (/SUBSYSTEM:WINDOWS)

c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言

(2)設(shè)置入口點(diǎn),解決方案上,右鍵->屬性->鏈接器->高級->入口點(diǎn),設(shè)置成:WinMainCRTStartup

c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言

2.未能加載文件或程序集“XXX.dll”或它的某個依賴項的解決方法

這個問題有時候比較隱蔽,正常情況下應(yīng)用程序查找依賴的dll時,順序為先查找程序exe的輸出路徑,如果沒有找到,那么會去C:\Windows\System32或System64文件夾中查找。

這種情況下我們只需要添加相關(guān)的dll到輸出文件夾下就能解決錯誤,但是當(dāng)你添加了對應(yīng)的依賴項之后仍然報相關(guān)錯誤:
c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言
這時候你可能覺得無法理解從而陷入誤區(qū),然而事實(shí)上在這種多級的引用中,有可能你當(dāng)前直接引用了A.dll,然后A.dll是一個CLR動態(tài)庫引用了B.dll。如果A.dll找到了,但是A.dll依賴的B.dll沒有找到,也會報上述錯誤,但這時它有可能只會提示沒有找到A.dll。所以你需要把相關(guān)的依賴項全部都放在一個輸出文件夾中來避免這種情況,當(dāng)然也有可能你不清楚你所使用的動態(tài)庫是否引用了第三方DLL,此時我們可以用Visual Studio中的dumpbin.exe工具查找A.dll的依賴項。

3.所生成項目的處理器框架“MSIL”與引用“xxx”的處理器架構(gòu)“AMD64”不匹配

這是由于你的C#程序與動態(tài)庫的生成配置不同導(dǎo)致的,將兩者進(jìn)行統(tǒng)一即可解決:
c#調(diào)用c++動態(tài)庫,C#,c#,c++,開發(fā)語言

4.System.EntryPointNotFoundException: '無法在 DLL“xxx.dll”中找到名為“xx”的入口點(diǎn)。

在系統(tǒng)內(nèi)的函數(shù)名稱不對,遇到這個問題可以用工具查看內(nèi)部名稱,發(fā)覺函數(shù)名稱并不是 “xx” 而是類似“?xx@@YAHHH@Z”這種不合法的形式。

原因為dll導(dǎo)出的格式不對,給c#調(diào)用時需要增加extern “C”,標(biāo)準(zhǔn)C格式。


_declspec(dllexport) int sum(int a, int b);//給c++調(diào)用
 
extern "C" __declspec(dllexport) int sum(int a, int b);//給c#調(diào)用

這一點(diǎn)在前文生成托管動態(tài)庫中提到過。

5.錯誤 LNK2019 無法解析的外部符號

這個如果是運(yùn)行時報錯,常見的原因是你引用了某個庫的函數(shù),然后也正確添加了它的頭文件路徑,vs在寫代碼階段可以找到這個函數(shù)的定義,但是,由于你沒有添加或者正確設(shè)置這個庫的lib或者dll路徑的話,那么vs就會在運(yùn)行時候報錯無法解析的外部符號。庫目錄(lib文件目錄)是在項目->屬性->配置屬性→VC++目錄→庫目錄里進(jìn)行添加,這一點(diǎn)在前文配置CLR項目中有詳細(xì)步驟。

第二種可能是類似第4點(diǎn)錯誤,你沒有正確的設(shè)置導(dǎo)出格式,需要增加相應(yīng)的定義。

同樣的第3點(diǎn)錯誤也可能導(dǎo)致這個問題。

除了前幾種可能,還有一點(diǎn)就是lib的覆蓋問題,引用動態(tài)庫,在項目生成中如果更改lib生成路徑,而正好引用該lib的項目又同時包含了原來的和重新生成的兩個lib路徑,編譯器就有可能鏈接的還是原來的lib,就會導(dǎo)致這個問題。

綜上所述,出現(xiàn)這個問題除了低級的拼寫錯誤外,無非就是沒有正確的引用相關(guān)的依賴文件,或是程序和他所引用的依賴同時引用了相關(guān)依賴但是版本不一致。

6.CS0570 '現(xiàn)用語言不支持xxx

這個比較常見是dll的問題,解決方案中有一個類庫項目,原來是引用的dll文件,后來又在本解決方案中建了一個一樣的類庫項目,有的項目直接引用的是這個類庫項目,有的又是引用的dll文件。

后來統(tǒng)一引用類庫項目就能編譯成功了。

還有一種可能則是函數(shù)的參數(shù)不兼容,假設(shè)你引用了一個MFC項目需要輸入一個CString類型的參數(shù),而C#中的String類型不能替代或是強(qiáng)制轉(zhuǎn)換也會出現(xiàn)問題。

六、總結(jié)

使用動態(tài)庫讓我們的程序有了更多可能,同時可以兼容不同的語言,但是在引用過程中容易出現(xiàn)各種問題,特別要遵循一定的規(guī)范,否則在復(fù)雜操作時會有意想不到的問題。但是使用得當(dāng)會是不可多得的助力!文章來源地址http://www.zghlxwxcb.cn/news/detail-559095.html

到了這里,關(guān)于C#調(diào)用C++動態(tài)庫的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • C#調(diào)用C++ dll異常排查

    C#調(diào)用C++ dll異常排查

    最近在做的一款程序,長時間運(yùn)行總會出現(xiàn)莫名的問題。有時是自動關(guān)閉,有時程序報錯,有時調(diào)用的dll異?!?由于開始與C++組合作時,使用其提供的dll出現(xiàn)過數(shù)據(jù)讀寫時異常(內(nèi)存操作異常),于是懷疑他們提供的dll有內(nèi)存泄漏。于是想通過日志或其它方法來確認(rèn)這個猜

    2024年01月21日
    瀏覽(28)
  • C#調(diào)用C++類,托管C++方式實(shí)現(xiàn)(創(chuàng)建C++ CLR dll項目)

    C#調(diào)用C++類,托管C++方式實(shí)現(xiàn)(創(chuàng)建C++ CLR dll項目)

    ????????由于C#編寫的是托管代碼,編譯生成微軟中間語言,而C++代碼則編譯生成本地機(jī)器碼(這種C++也有叫做本地C++或者非托管C++,VC6.0就是用于開發(fā)非托管C++代碼的平臺),這兩種語言進(jìn)行混合編程就存在一定困難。比較常用的方法是使用DllImport的方法,這種方法在網(wǎng)

    2024年02月07日
    瀏覽(15)
  • Unity Native Plugin C#和C++互相調(diào)用

    Unity Native Plugin C#和C++互相調(diào)用

    官方鏈接 1.DLL的方式: C++代碼:編譯成DLL,導(dǎo)入Unity C#代碼: 2.還有一種是C++源碼作為插件,只支持il2cpp。 C++代碼:直接放到Unity的Assets目錄下 C#源文件:區(qū)別只在導(dǎo)入時不寫具體的文件名,寫:__Internal即可,因為用IL2CPP 后端的方式,會把C++源文件放到工程內(nèi)部一塊編譯。

    2024年02月12日
    瀏覽(16)
  • C#調(diào)用OpenCV(C++原版)思路和實(shí)現(xiàn)方法(小白教程)

    C#調(diào)用OpenCV(C++原版)思路和實(shí)現(xiàn)方法(小白教程)

    原本想著用OpenCV的話,只需考慮在編程語言環(huán)境下調(diào)用對應(yīng)的庫(包)就行了,因為之前也是做了一個利用python(OpenCV-python接口)下編寫了一個停車場空位識別項目,但是沒接觸過實(shí)際的我,天真地認(rèn)為這些語言封裝庫接口已經(jīng)可以實(shí)現(xiàn)原本OpenCV的所有功能,但是看了面試題

    2024年02月02日
    瀏覽(18)
  • C++和C#程序語言的區(qū)別

    一直學(xué)習(xí)C++和C#,兩者之間的區(qū)別總結(jié)一下 目錄 一、兩種語言概述 C++語言 C#語言 二、兩種語言對比 2.1

    2024年02月09日
    瀏覽(17)
  • C#編程語言的優(yōu)勢與C++對比

    ? ? ? ?C#語言是由 C/C++演變而來的,是微軟推出的一種基于.NET框架的、面向?qū)ο蟮母呒壘幊陶Z言。以.NET框架類庫作為基礎(chǔ),擁有類似Visual Basic的快速開發(fā)能力。簡單易學(xué),入門超快,減少了煩人的指針,有統(tǒng)一的操作符/修飾符/運(yùn)算符,使用起來極其舒心。 ? ? ? ??對于

    2024年02月09日
    瀏覽(34)
  • EtherNet/IP開發(fā):JAVA、C#和C++開發(fā)源代碼

    EtherNet/IP開發(fā):JAVA、C#和C++開發(fā)源代碼

    示例使用VS2010開發(fā)EtherNet/IP 開發(fā)語言使用C++ C++開發(fā)出來的程序,提供C標(biāo)準(zhǔn)API后,將可以提供給Dlphi、Labview、VB、QT、C#、CC++、C#、Java等幾乎所有編程語言使用。 ① 在底層我們將采用socket和多線程方式開發(fā),在數(shù)據(jù)處理方面使用指針為主。 ②?EtherNet/IP在設(shè)計之初就是為高效

    2024年01月21日
    瀏覽(85)
  • 0基礎(chǔ)開發(fā)EtherNet/IP:協(xié)議格式,JAVA、C#、C++處理

    0基礎(chǔ)開發(fā)EtherNet/IP:協(xié)議格式,JAVA、C#、C++處理

    經(jīng)過一陣倒騰,把CIP、Ethernet/ip協(xié)議搞到手 協(xié)議的概念和理論就不提及了,上網(wǎng)隨便一搜索EtherNet/IP遍地都是。 直接將協(xié)議關(guān)鍵點(diǎn)列舉出來吧。 更多協(xié)議資料 www.jngbus.com 通訊軟件群 30806722 這里講解的是TCP和UDP協(xié)議的格式,EtherNet/IP數(shù)據(jù)所處位置。 ① 具體內(nèi)容需要大家自己進(jìn)

    2024年01月21日
    瀏覽(18)
  • Java、Python、C++和C#的界面開發(fā)框架和工具的重新介紹

    好的,以下是Java、Python、C++和C#的界面開發(fā)框架和工具的重新介紹: Java界面開發(fā): Swing: 是Java提供的一個基于組件的GUI工具包,可以創(chuàng)建跨平臺的圖形用戶界面。它提供了豐富的組件和布局管理器,使得界面開發(fā)相對簡單。Swing是Java AWT的繼承者,支持更多的功能和外觀。

    2024年02月02日
    瀏覽(25)
  • [軟件工具]opencv-svm快速訓(xùn)練助手教程解決opencv C++ SVM模型訓(xùn)練與分類實(shí)現(xiàn)任務(wù)支持C# python調(diào)用

    [軟件工具]opencv-svm快速訓(xùn)練助手教程解決opencv C++ SVM模型訓(xùn)練與分類實(shí)現(xiàn)任務(wù)支持C# python調(diào)用

    opencv中已經(jīng)提供了svm算法可以對圖像實(shí)現(xiàn)多分類,使用svm算法對圖像分類的任務(wù)多用于場景簡單且對時間有要求的場景,因為opencv的svm訓(xùn)練一般只需要很短時間就可以完成訓(xùn)練任務(wù)。但是目前網(wǎng)上沒有一個工具很好解決訓(xùn)練問題,大部分需要自己編程去實(shí)現(xiàn)訓(xùn)練任務(wù),這個對

    2024年02月06日
    瀏覽(34)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包