1. 程式人生 > >linux下C C++呼叫C#

linux下C C++呼叫C#

舊的MFC專案呼叫的一些庫用C#來寫(編譯成DLL庫),現在專案要移植到linux下,也想在linux下用C來呼叫C#,linux不支援C#,需要安裝linux下C#的執行環境mono。
呼叫原理大概是這樣子的,linux下的C/C++不能直接呼叫C#函式的,而是通過mono提供的api,建立一個C#的執行環境,在該環境中建立C#類,再通過mono api間接呼叫C#。
mono的安裝參考www.mono-project.com官網的,直接用apt-get安裝即可,很方便。

callcsharp.cpp

#include <mono/jit/jit.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/debug-helpers.h>
#include <assert.h>
#include <stdio.h>

#define print(fmt, args...) printf(fmt "\n", ##args);
#define TRUE    1
#define FALSE   0
#define USE_OLD_LIB 0

int main()
{

    const char *dlllib = "./DataMatrixLibrary.dll";
    MonoDomain *domain = mono_jit_init("Mydomain");
    if (!domain) { 
        print("domain is null");
    }
    MonoAssembly *assembly = mono_domain_assembly_open(domain, dlllib);
    if (!assembly) {
        print("assembly is null");
        return -1;
    }
    MonoImage *image = mono_assembly_get_image(assembly);
    if (!image) {
        print("image is null");
        return -1;
    }

    //----------------------------------------------------------------->    
    /*
    //這裡是對C#類中static函式的引腳,比較簡單,不用建立類
    MonoMethodDesc *desc_static = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:Test", TRUE);
    if (!desc_static) {
        print("desc_static is null");
        return -1;
    }
    MonoMethod *method_static = mono_method_desc_search_in_image(desc_static, image);
    if (!method_static) {
        print("method_static is null");
        return -1;
    }
    mono_runtime_invoke(method_static, NULL, NULL, NULL);
    */
    //DataMatrixLibrary是namespace,AisDataMatrix是類
    MonoClass *my_class = mono_class_from_name(image, "DataMatrixLibrary", "AisDataMatrix");
    if (!my_class) {
        print("my_class is null");
        return -1;
    }
    //建立類
    MonoObject *class_instance = mono_object_new(domain, my_class);
    if (!class_instance) {
        print("class instance is null");
        return -1;
    }
    //呼叫類的construct函式,沒有引數,如果有引數,參考mono的文件,裡邊有介紹怎樣呼叫有引數的建構函式
    mono_runtime_object_init(class_instance);
    //----------------------------------------------------------------->
    #if USE_OLD_LIB > 0
    //獲取函式說明,最後一個引數為TRUE表示第一個引數要包括namespace
    MonoMethodDesc *desc_SetBarcodeAngle = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarCodeAngel", TRUE);
    #else
    MonoMethodDesc *desc_SetBarcodeAngle = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarcodeAngel", TRUE);
    #endif
    if (!desc_SetBarcodeAngle) {
        print("desc is null");
        return -1;
    }
    //找到該函式
    MonoMethod *method_SetBarcodeAngle = mono_method_desc_search_in_image(desc_SetBarcodeAngle, image);
    if (!method_SetBarcodeAngle) {
        print("method is null");
        return -1;
    }
    //呼叫C#函式,返回值我沒處理,mono文件有介紹怎樣獲取返回值
    void *args[1];
    int angel = 10;
    args[0] = &angel;
    mono_runtime_invoke(method_SetBarcodeAngle, class_instance, args, NULL);
    //----------------------------------------------------------------->
    #if USE_OLD_LIB > 0
    MonoMethodDesc *desc_SetFontFamily = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetFontFamily", TRUE);
    #else
    MonoMethodDesc *desc_SetFontFamily = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarcodeFontFamily", TRUE);
    #endif
    if (!desc_SetFontFamily) {
        print("desc_SetFontFamily is null");
        return -1;
    }
    MonoMethod *method_SetFontFamily = mono_method_desc_search_in_image(desc_SetFontFamily, image);
    if (!method_SetFontFamily) {
        print("method_SetFontFamily is null");
        return -1;
    }
    args[0] = mono_string_new(domain, "Arial");
    mono_runtime_invoke(method_SetFontFamily, class_instance, args, NULL);
    //----------------------------------------------------------------->
    #if USE_OLD_LIB > 0
    MonoMethodDesc *desc_SetBarCodeFormat = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarCodeFormat", TRUE);
    #else
    MonoMethodDesc *desc_SetBarCodeFormat = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarcodeFormat", TRUE);
    #endif
    if (!desc_SetBarCodeFormat) {
        print("desc_SetBarCodeFormat is null");
        return -1;
    }
    MonoMethod *method_SetBarCodeFormat = mono_method_desc_search_in_image(desc_SetBarCodeFormat, image);
    if (!method_SetBarCodeFormat) {
        print("method_SetBarCodeFormat is null");
        return -1;
    }
    int bar_format = 0;
    args[0] = &bar_format;
    mono_runtime_invoke(method_SetBarCodeFormat, class_instance, args, NULL);
    //----------------------------------------------------------------->
    #if USE_OLD_LIB > 0
    MonoMethodDesc *desc_SetBarCodeWidth = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarCodeWidth", TRUE);
    #else
    MonoMethodDesc *desc_SetBarCodeWidth = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarcodeWidth", TRUE);
    #endif
    if (!desc_SetBarCodeWidth) {
        print("desc_SetBarCodeWidth is null");
        return -1;
    }
    MonoMethod *method_SetBarCodeWidth = mono_method_desc_search_in_image(desc_SetBarCodeWidth, image);
    if (!method_SetBarCodeWidth) {
        print("method_SetBarCodeFormat is null");
        return -1;
    }
    int codeWidth = 555;
    args[0] = &codeWidth;
    mono_runtime_invoke(method_SetBarCodeWidth, class_instance, args, NULL);
    //----------------------------------------------------------------->
    MonoMethodDesc *desc_SetImageWidth = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetImageWidth", TRUE);
    if (!desc_SetImageWidth) {
        print("desc is null");
        return -1;
    }
    MonoMethod *method_SetImageWidth = mono_method_desc_search_in_image(desc_SetImageWidth, image);
    if (!method_SetImageWidth) {
        print("method_SetImageWidth is null");
        return -1;
    }
    int imageWidth = 569;
    args[0] = &imageWidth;
    mono_runtime_invoke(method_SetImageWidth, class_instance, args, NULL);
    //----------------------------------------------------------------->
    #if USE_OLD_LIB > 0
    MonoMethodDesc *desc_SetIsNegative = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetIsNegative", TRUE);
    #else
    MonoMethodDesc *desc_SetIsNegative = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarcodeNegative", TRUE);
    #endif
    if (!desc_SetIsNegative) {
        print("desc is null");
        return -1;
    }
    MonoMethod *method_SetIsNegative = mono_method_desc_search_in_image(desc_SetIsNegative, image);
    if (!method_SetIsNegative) {
        print("method_SetIsNegative is null");
        return -1;
    }
    int isNeg = 1;
    args[0] = &isNeg;
    mono_runtime_invoke(method_SetIsNegative, class_instance, args, NULL);
    //----------------------------------------------------------------->
    #if USE_OLD_LIB > 0
    MonoMethodDesc *desc_SetIsVertical = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetIsVertical", TRUE);
    #else
    MonoMethodDesc *desc_SetIsVertical = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarcodeFlip", TRUE);
    #endif
    if (!desc_SetIsVertical) {
        print("desc_SetIsVertical is null");
        return -1;
    }
    MonoMethod *method_SetIsVertical = mono_method_desc_search_in_image(desc_SetIsVertical, image);
    if (!method_SetIsVertical) {
        print("method_SetIsVertical is null");
        return -1;
    }
    int isVer = 1;
    args[0] = &isVer;
    mono_runtime_invoke(method_SetIsVertical, class_instance, args, NULL);
    //----------------------------------------------------------------->
    #if USE_OLD_LIB > 0
    MonoMethodDesc *desc_SetIsMirror = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetIsMirror", TRUE);
    #else
    MonoMethodDesc *desc_SetIsMirror = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetBarcodeMirror", TRUE);
    #endif
    if (!desc_SetIsMirror) {
        print("desc is null");
        return -1;
    }
    MonoMethod *method_SetIsMirror = mono_method_desc_search_in_image(desc_SetIsMirror, image);
    if (!method_SetIsMirror) {
        print("method_SetIsMirror null");
        return -1;
    }
    int isMirror = 1;
    args[0] = &isMirror;
    mono_runtime_invoke(method_SetIsMirror, class_instance, args, NULL);
    //----------------------------------------------------------------->
    #if USE_OLD_LIB > 0
    MonoMethodDesc *desc_SetImageBackColor = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetImageBackColor", TRUE);
    #else
    MonoMethodDesc *desc_SetImageBackColor = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:SetImageBackground", TRUE);
    #endif
    if (!desc_SetImageBackColor) {
        print("desc_SetImageBackColor is null");
        return -1;
    }
    MonoMethod *method_SetImageBackColor = mono_method_desc_search_in_image(desc_SetImageBackColor, image);
    if (!method_SetImageBackColor) {
        print("method_SetImageBackColor null");
        return -1;
    }
    int imageBackcolor = 1;
    args[0] = &imageBackcolor;
    mono_runtime_invoke(method_SetImageBackColor, class_instance, args, NULL);
    //----------------------------------------------------------------->
    #if USE_OLD_LIB > 0
    MonoMethodDesc *desc_CreateFile = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:CreateFile", TRUE);
    #else
    MonoMethodDesc *desc_CreateFile = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:CreateBarcodeFile", TRUE);
    #endif
    if (!desc_CreateFile) {
        print("desc_CreateFile is null");
        return -1;
    }
    MonoMethod *method_CreateFile = mono_method_desc_search_in_image(desc_CreateFile, image);
    if (!method_CreateFile) {
        print("method_CreateFile null");
        return -1;
    }
    //這個函式有兩個string引數
    void *args2[2];
    args2[0] = mono_string_new(domain, "0017362S123E123RX+LLSSSCCF1");
    args2[1] = mono_string_new(domain, "/home/i/csharp");
    mono_runtime_invoke(method_CreateFile, class_instance, args2, NULL);
    /*
    MonoMethodDesc *desc_GetBarCodeSize = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:GetBarCodeSize", TRUE);
    if (!desc) {
        print("desc is null");
        return -1;
    }
    int codeWidth = 555;
    args[0] = &codeWidth;
    mono_runtime_invoke(method_SetBarCodeWidth, class_instance, args, NULL)

    MonoMethodDesc *desc_CreateByte = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:CreateByte", TRUE);
    if (!desc) {
        print("desc is null");
        return -1;
    }
    int codeWidth = 555;
    args[0] = &codeWidth;
    mono_runtime_invoke(method_SetBarCodeWidth, class_instance, args, NULL)

    MonoMethodDesc *desc_CreateBmp = mono_method_desc_new("DataMatrixLibrary.AisDataMatrix:CreateBmp", TRUE);
    if (!desc) {
        print("desc is null");
        return -1;
    }
    int codeWidth = 555;
    args[0] = &codeWidth;
    mono_runtime_invoke(method_SetBarCodeWidth, class_instance, args, NULL)
    */
    mono_jit_cleanup(domain);
    print("call c# success!!!");
    return 0;
}

編譯:

g++ -o  callcsharp  callcsharp.cpp `pkg-config --cflags --libs mono-2`

mono庫安裝在/usr/lib/mono下。
能呼叫C#,但是發現mono對C#支援不是很好,有些庫函式執行不正常,分另在linux和windows對比測試,呼叫函式時引數都是一樣(可以在C#用System.console.write指印出來),但是Linux和windows的返回值是不一樣,說明是環境的問題。