最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#?DLL跨語言調(diào)用的兩種實(shí)現(xiàn)方法

 更新時間:2026年03月02日 09:39:34   作者:蟈蟈(GuoGuo)  
這篇文章主要介紹了如何編寫能被其他編程語言調(diào)用的C#?DLL,包括兩種主流方式:通過COM接口或P/Invoke封裝非托管導(dǎo)出函數(shù),重點(diǎn)在于讓C#?DLL符合跨語言調(diào)用的標(biāo)準(zhǔn),包括數(shù)據(jù)類型兼容性、框架選擇和錯誤處理等關(guān)鍵要點(diǎn),需要的朋友可以參考下

你想知道如何編寫能被其他編程語言(如C++、Python、Java等)調(diào)用的C# DLL,這需要解決不同語言間的互操作(Interop)問題,核心是讓C# DLL符合跨語言調(diào)用的標(biāo)準(zhǔn)。

一、核心思路:讓C# DLL支持COM/非托管調(diào)用

普通C# DLL基于.NET托管代碼,非.NET語言(如C++原生、Python)無法直接調(diào)用,需要通過以下兩種主流方式實(shí)現(xiàn)跨語言調(diào)用:

  1. 方式1:將C# DLL注冊為COM組件(兼容絕大多數(shù)語言:C++、VB6、Python、Java等);
  2. 方式2:通過P/Invoke封裝非托管導(dǎo)出函數(shù)(主要適配C/C++等原生語言)。

下面優(yōu)先講解最通用的COM組件方式,再補(bǔ)充P/Invoke方式。

方式1:創(chuàng)建可注冊為COM的C# DLL(通用跨語言)

步驟1:創(chuàng)建類庫項目并配置COM兼容

  1. 打開Visual Studio,創(chuàng)建「類庫(.NET Framework)」項目(.NET Core/.NET 5+需額外配置,推薦先用.NET Framework做兼容),命名為ComInteropDll。
  2. 右鍵項目→「屬性」→「應(yīng)用程序」→「程序集信息」,勾選「使程序集COM可見」。
  3. 右鍵項目→「屬性」→「生成」,勾選「為COM互操作注冊」(僅開發(fā)環(huán)境需要,發(fā)布時手動注冊)。

步驟2:編寫COM兼容的C#代碼

COM要求必須通過接口 暴露方法,且需要給接口/類添加Guid(唯一標(biāo)識),示例代碼如下:

using System;
using System.Runtime.InteropServices;

// 1. 為接口添加唯一Guid(可通過VS工具生成:工具→創(chuàng)建GUID→選注冊表格式,去掉{})
[Guid("12345678-1234-1234-1234-1234567890AB")]
// 2. 標(biāo)記為COM可見的接口
[ComVisible(true)]
public interface ICalculator
{
    // COM接口方法不能有重載,參數(shù)/返回值盡量用基礎(chǔ)類型(int、string、double等)
    int Add(int a, int b);
    string ReverseString(string input);
}

// 3. 為實(shí)現(xiàn)類添加唯一Guid
[Guid("87654321-4321-4321-4321-BA0987654321")]
[ComVisible(true)]
public class Calculator : ICalculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public string ReverseString(string input)
    {
        if (string.IsNullOrEmpty(input))
            throw new ArgumentNullException(nameof(input));
        
        char[] arr = input.ToCharArray();
        Array.Reverse(arr);
        return new string(arr);
    }
}

步驟3:編譯并注冊COM組件

按F6編譯項目,生成ComInteropDll.dllComInteropDll.tlb(類型庫文件,供其他語言識別)。

注冊COM組件(管理員權(quán)限運(yùn)行CMD):

# 替換為你的DLL路徑(Release版建議用Release目錄)
regasm /codebase "C:\ComInteropDll\bin\Debug\ComInteropDll.dll"

卸載COM組件(如需):regasm /u "你的DLL路徑"

步驟4:不同語言調(diào)用該COM DLL示例

示例1:Python調(diào)用(使用pywin32庫)

# 先安裝依賴:pip install pywin32
import win32com.client

# 創(chuàng)建COM對象(參數(shù)是接口/類的ProgID,或直接用Guid)
# 方式1:用類名(需確保項目屬性中配置了ProgID,或手動指定)
calculator = win32com.client.Dispatch("ComInteropDll.Calculator")

# 調(diào)用方法
sum_result = calculator.Add(10, 25)
reverse_result = calculator.ReverseString("Python Call C# DLL")

print(f"兩數(shù)之和:{sum_result}")  # 輸出:35
print(f"反轉(zhuǎn)字符串:{reverse_result}")  # 輸出:LLD #C llaC nohtyP

示例2:C++原生調(diào)用(使用COM接口)

#include <iostream>
#include <Windows.h>
// 導(dǎo)入類型庫(替換為你的tlb文件路徑)
#import "C:\ComInteropDll\bin\Debug\ComInteropDll.tlb" no_namespace

int main()
{
    // 初始化COM庫
    CoInitialize(NULL);

    // 創(chuàng)建COM對象
    ICalculator* pCalculator = NULL;
    HRESULT hr = CoCreateInstance(
        __uuidof(Calculator),  // 類的Guid
        NULL,
        CLSCTX_INPROC_SERVER,
        __uuidof(ICalculator), // 接口的Guid
        (void**)&pCalculator
    );

    if (SUCCEEDED(hr))
    {
        // 調(diào)用方法
        int sum = 0;
        pCalculator->Add(100, 200, &sum);
        
        BSTR input = SysAllocString(L"C++ Call C# COM DLL");
        BSTR reversed = NULL;
        pCalculator->ReverseString(input, &reversed);

        // 輸出結(jié)果
        std::cout << "Sum: " << sum << std::endl; // 輸出:300
        wprintf(L"Reversed: %s\n", reversed);    // 輸出:LLD MOC #C llaC ++C

        // 釋放資源
        SysFreeString(input);
        SysFreeString(reversed);
        pCalculator->Release();
    }

    // 釋放COM庫
    CoUninitialize();
    return 0;
}

方式2:P/Invoke導(dǎo)出非托管函數(shù)(適配C/C++)

如果僅需給C/C++調(diào)用,可通過DllExport庫直接導(dǎo)出非托管函數(shù)(C#原生不支持直接導(dǎo)出函數(shù),需第三方庫)。

步驟1:安裝DllExport庫

在NuGet包管理器中安裝:UnmanagedExports(注意:僅支持.NET Framework)。

步驟2:編寫導(dǎo)出函數(shù)的C#代碼

using System;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;

namespace PInvokeDll
{
    public class MyExports
    {
        // 導(dǎo)出Add函數(shù),供C/C++調(diào)用
        [DllExport("Add", CallingConvention = CallingConvention.Cdecl)]
        public static int Add(int a, int b)
        {
            return a + b;
        }

        // 導(dǎo)出反轉(zhuǎn)字符串函數(shù)(注意字符編碼適配)
        [DllExport("ReverseString", CallingConvention = CallingConvention.Cdecl)]
        public static IntPtr ReverseString([MarshalAs(UnmanagedType.LPStr)] string input)
        {
            if (string.IsNullOrEmpty(input))
                return IntPtr.Zero;
            
            char[] arr = input.ToCharArray();
            Array.Reverse(arr);
            string result = new string(arr);
            
            // 分配非托管內(nèi)存并返回(調(diào)用方需釋放)
            return Marshal.StringToHGlobalAnsi(result);
        }

        // 提供釋放內(nèi)存的函數(shù),供調(diào)用方使用
        [DllExport("FreeString", CallingConvention = CallingConvention.Cdecl)]
        public static void FreeString(IntPtr ptr)
        {
            if (ptr != IntPtr.Zero)
                Marshal.FreeHGlobal(ptr);
        }
    }
}

步驟3:C++調(diào)用該DLL

#include <iostream>
#include <Windows.h>

// 聲明導(dǎo)入的函數(shù)
extern "C" __declspec(dllimport) int Add(int a, int b);
extern "C" __declspec(dllimport) char* ReverseString(const char* input);
extern "C" __declspec(dllimport) void FreeString(char* ptr);

int main()
{
    // 調(diào)用Add函數(shù)
    int sum = Add(5, 8);
    std::cout << "Add result: " << sum << std::endl; // 輸出:13

    // 調(diào)用ReverseString函數(shù)
    char* reversed = ReverseString("Hello C++");
    std::cout << "Reversed: " << reversed << std::endl; // 輸出:++C olleH
    FreeString(reversed); // 釋放內(nèi)存

    return 0;
}

關(guān)鍵注意事項

  1. 數(shù)據(jù)類型兼容:跨語言調(diào)用時,優(yōu)先使用基礎(chǔ)數(shù)據(jù)類型(int、double、string),避免復(fù)雜自定義類型;字符串需注意編碼(ANSI/UTF-8/UTF-16)。
  2. 框架選擇
    • .NET Framework:對COM/P/Invoke支持最好,兼容老語言;
    • .NET Core/.NET 5+:需用ComHostNativeAOT編譯為原生DLL,步驟更復(fù)雜。
  3. 錯誤處理:跨語言調(diào)用時,C#中的異常無法直接傳遞給非托管語言,建議返回錯誤碼而非拋出異常。
  4. 64位/32位適配:編譯DLL和調(diào)用程序時,需保持位數(shù)一致(均為x86或x64),否則會調(diào)用失敗。

總結(jié)

  1. 通用跨語言方案:將C# DLL注冊為COM組件,適配Python、Java、C++等絕大多數(shù)語言,核心是通過ComVisibleGuid暴露接口,并注冊COM。
  2. C/C++專屬方案:使用UnmanagedExports庫導(dǎo)出非托管函數(shù),通過P/Invoke調(diào)用,更輕量但僅適配C/C++。
  3. 核心要點(diǎn):保持?jǐn)?shù)據(jù)類型簡單、位數(shù)一致、處理好內(nèi)存釋放(尤其是字符串),是跨語言調(diào)用的關(guān)鍵。

以上就是C# DLL跨語言調(diào)用的兩種實(shí)現(xiàn)方法的詳細(xì)內(nèi)容,更多關(guān)于C# DLL跨語言調(diào)用的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

治县。| 紫金县| 连山| 济源市| 富源县| 昌吉市| 清水河县| 宣汉县| 普宁市| 宜兰县| 怀仁县| 深泽县| 兴城市| 璧山县| 水城县| 黄浦区| 儋州市| 汉沽区| 抚州市| 台中县| 乐东| 壶关县| 奎屯市| 盐城市| 伊春市| 含山县| 利津县| 桃源县| 望城县| 绥芬河市| 广安市| 灌南县| 朝阳市| 怀来县| 沧州市| 阿合奇县| 信阳市| 普格县| 昌邑市| 虹口区| 文登市|