其實不知道這個文章到底要分類再C#還是C++呢....

麻~C++的部分含量較重,那就分在C++好了

 

 

這篇會使用到extern "C"DllImport,建議先行了解

以下皆在Visual Studio 2015上完成!

 

剛開始時先檔案→新增→專案,選擇Visual C++的Win32專案,命名為ForCSharpCall

應用程式設定選擇DLL和空專案

 

完成後是只有資料夾而已

 

此時對ForCSharpCall點右鍵→屬性(property),組態屬性→紅框處選擇支援,若不支援則無法給C#呼叫

 

然後新增一些檔案

 

先撰寫ForCSharpCallDefine.h


#pragma once

 

class Calculate
{
public:
    Calculate();//預設的空建構子

    int Addition(int a, int b);//加法

    int Subtraction(int a, int b);//減法

    int Multiplication(int a, int b);//乘法

    float Division(int a, int b);//除法
};


 

再來是ForCSharpCallImplement.cpp,很簡單的加減乘除而已


#include "ForCSharpCallDefine.h"

Calculate::Calculate()
{

}

int Calculate::Addition(int a, int b)
{
    return a + b;
}

int Calculate::Subtraction(int a, int b)
{
    return a - b;
}

int Calculate::Multiplication(int a, int b)
{
    return a * b;
}

float Calculate::Division(int a, int b)
{
    return a / b;
}


 

最後是最重要的!連接C#和C++的部分

ForExternCall.cpp


#ifdef FORCSHARPCALL_EXPORTS //同專案名稱,只是後面固定為_EXPORTS
#define FORCSHARPCALL_API __declspec(dllexport) //請注意!正確的是Export要亮起
#else
#define FORCSHARPCALL_API __declspec(dllimport)
#endif

#include "ForCSharpCallDefine.h"

//可以將class的物件宣告在外面變成全域
//Calculate cal;

extern "C" FORCSHARPCALL_API int Add(int a, int b)
{
    Calculate cal;//宣告在function內,只有該function能使用
    return cal.Addition(a, b);
}

extern "C" FORCSHARPCALL_API int Sub(int a, int b)
{
    Calculate cal;//宣告在function內,只有該function能使用
    return cal.Subtraction(a, b);
}

extern "C" FORCSHARPCALL_API int Multi(int a, int b)
{
    Calculate cal;//宣告在function內,只有該function能使用
    return cal.Multiplication(a, b);
}

extern "C" FORCSHARPCALL_API float Div(int a, int b)
{
    Calculate cal;//宣告在function內,只有該function能使用
    return cal.Division(a, b);
}


 

以上都完成後,按下建置→建置方案(Ctrl+Shift+B)

 

 

 

之後就是建立C#專案,從C#呼叫啦!

為了方便,所以建立了一個主控台應用程式(Console Application),命名為TestCall


using System;
using System.Runtime.InteropServices;

namespace TestCall
{
    class Program
    {
        //傳入和傳出的型態格式必須同ForExternCall.cpp內的設置!!

        //我將dll檔放到D:,然後設置進入點
        [DllImport("D:/ForCSharpCall.dll", EntryPoint="Add", CallingConvention = CallingConvention.Cdecl)]
        private static extern int add(int a, int b);

        //也可以不設置進入點,但函數名稱必須相同
        [DllImport("D:/ForCSharpCall.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int Sub(int a, int b);

        [DllImport("D:/ForCSharpCall.dll", EntryPoint = "Multi", CallingConvention = CallingConvention.Cdecl)]
        private static extern int mul(int a, int b);

        [DllImport("D:/ForCSharpCall.dll", EntryPoint = "Div", CallingConvention = CallingConvention.Cdecl)]
        private static extern float div(int a, int b);

        static void Main(string[] args)
        {
                Console.WriteLine(add(10, 20));
                Console.WriteLine(Sub(10, 20));
                Console.WriteLine(mul(10, 20));
                Console.WriteLine(div(10, 20));

                Console.ReadKey();

        }
    }
}


執行結果如下(第四個是0沒錯,因為兩個int相除一定是int,只是完成後才突然想到。反正大家知道就好,我懶得改了)

 

 

 

如果出現這種錯誤訊息:System.BadImageFormatException: 試圖載入格式錯誤的程式。 (發生例外狀況於 HRESULT: 0x8007000B)

原因就是Visual Studio編譯環境的問題,將Any CPU或x64改成x86即可解決。

arrow
arrow
    全站熱搜

    Yang 發表在 痞客邦 留言(7) 人氣()