C#調用C++ DLL動態庫的兩種方式


第一種方式:C++導出函數, c#dllimport 的方式

在很多地方都看到過,如[dllimport “user32.dll”]這種代碼,調用windows API,就是通過這種方式實現。

例子:新建C++項目,創建動態鏈接庫(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方法為一個導出方法,外部可見 

然后,dllmain.cpp中添加代碼:

#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;
}

#ifdef _MANAGED
#pragma managed(push, off)
#endif

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


#ifdef _MANAGED
#pragma managed(pop)
#endif

編譯通過后,找到目錄下生成的DLL(TESTDLL.dll),拷貝出來,放到C#的debug目錄(程序目錄)下, 然后新建C#程序:

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")]  //最關鍵的,導入該dll
        public extern static void MessageBoxShow();
        static void Main(string[] args)
        {
            MessageBoxShow();
        }
    }
}

然后運行可以看到結果:成功的調用了C++DLL中的方法。

 

第二種方式:

通過C++/CLI作為中間層,因為C++/CLI即可調用.NET的類庫,又可調用C++原生庫,

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

1、創建一個c++空項目

 

 

  項目創建完成,我們添加一個類,寫幾個方法,這兒就簡單寫一個計算器的加減乘除吧!

在CaculateData.h中添加如下代碼,定義幾個函數聲明;

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#ifdef CaculateDLL_EXPORTS
#define Calculate_EXPORTS __declspec(dllexport)
#else
#define Calculate_EXPORTS __declspec(dllimport)
#endif

extern "C" Calculate_EXPORTS int Add(int numberA, int numberB);

extern "C" Calculate_EXPORTS int Subtract(int numberA, int numberB);

extern "C" Calculate_EXPORTS int Multiplication(int numberA, int numberB);

extern "C" Calculate_EXPORTS  int Divided(int numberA, int numberB);

class CaculateData
{
public:
    CaculateData();
    ~CaculateData();

};

可以看到,#ifdef的宏沒有定義,所以我們需要添加一個宏:

項目右鍵---屬性---配置屬性---C/C++---預處理器---預處理器定義,將定義的宏添加進去;

 

可以看到,定義好了,顏色就變成紫色的,說明已經聲明了宏;

在CaculateData.cpp中實現這幾個方法;

 

#include "CaculateData.h"
#include <iostream>

CaculateData::CaculateData()
{
}


CaculateData::~CaculateData()
{
}

Calculate_EXPORTS int Add(int numberA, int numberB)
{
    return numberA + numberB;
}

Calculate_EXPORTS int Subtract(int numberA, int numberB)
{
    return numberA - numberB;
}

Calculate_EXPORTS int Multiplication(int numberA, int numberB)
{
    return numberA * numberB;
}

Calculate_EXPORTS int Divided(int numberA, int numberB)
{
    if (numberB == 0) {
        std::cout << "除數不能為空" << std::endl;
    }
    return numberA / numberB;
}

修改C++工程項目輸出目錄,這兒主要是便於CLI引用,我們這兒同意定義到Testinvoking項目的輸出目錄..\bin\Debug\netcoreapp2.2

(修改步驟:項目右鍵—屬性—配置屬性—常規—輸出目錄)

配置類型修改為:動態庫.dll (修改步驟:項目右鍵—屬性—配置屬性—常規—配置類型)

然后生成;

2、新建一個CLR項目

這個項目就是來實現C#調用C++的

因為需要調用Caculate.dll,所以需要引用它;

配置屬性—VC++目錄—庫目錄(把剛剛生成Caculate.dll的路徑添加進去)

 

 同時引用庫:

 

 添加一個類InvokeCon.cpp,用它來調用Caculate.dll中的方法

 InvokeCon.cpp代碼如下:

#include "InvokeCon.h"

InvokeCon::InvokeCon()
{
}

int InvokeCon::AddCli(int numberA, int numberB)
{
    return Add(numberA, numberB);
}

int InvokeCon::SubtractCli(int numberA, int numberB)
{
    return Subtract(numberA, numberB);
}

int InvokeCon::MultiplicationCli(int numberA, int numberB)
{
    return Multiplication(numberA, numberB);
}

int InvokeCon::DividedCli(int numberA, int numberB)
{
    return Divided(numberA, numberB);
}

InvokeCon.h代碼:

#pragma once

#include <iostream>
#include "C:\Users\tjy\source\repos\TestInvoking\Caculate\CaculateData.h"//引用庫聲明對應文件路徑
public ref class InvokeCon
{
public:
    InvokeCon();

    int AddCli(int numberA, int numberB);
    int SubtractCli(int numberA, int numberB);
    int MultiplicationCli(int numberA, int numberB);
    int DividedCli(int numberA, int numberB);
};

然后編譯,修改編譯類型為動態庫dll

 

3、c#通過引用CliDll.dll來調用Caculate中的方法

 然后生成:此時就產生了CliDll.dll庫

1、添加對Dll的引用;

2、在C#項目中添加測試代碼:

可以看到,此時就能夠調用多個方法,而且會有方法名提示!

using System;

namespace TestInvoking
{
    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("---------c#通過CLI調用C++類方法---------");
                Console.Write("請輸入numberA:");
                int numberA = Convert.ToInt32(Console.ReadLine());
                Console.Write("請輸入numberB:");
                int numberB = Convert.ToInt32(Console.ReadLine());

                InvokeCon invoke = new InvokeCon();
                int addResult = invoke.AddCli(numberA, numberB);
                int subResult = invoke.SubtractCli(numberA, numberB);
                int mutilResult = invoke.MultiplicationCli(numberA, numberB);
                int divResult = invoke.DividedCli(numberA, numberB);

                Console.WriteLine($"the {numberA} And {numberB} sum is:{addResult};sub is:{subResult};Mutil is:{mutilResult};div is:{divResult}");
            }
            catch(Exception ex)
            {
                Console.WriteLine($"ex:{ex}");
            }

            Console.WriteLine("執行成功");
            Console.ReadLine();
        }
    }
}

 OK,完成!

代碼已經放到了github,需要的朋友可以去看,就是這篇文章簡單的demo:

github地址:https://github.com/tomorrowGooddays/Invoke

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM