You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ubuntu下使用Python调用带参数的C#函数并获取返回结果

C# 适配Mono+Ubuntu16.04环境的ctypes调用实操指南

核心结论

  • 这套实现的最终操作流畅度和你之前用C++ extern "C" 导出的方案完全一致:Python侧全程用ctypes加载动态库、传参、拿返回值,无额外依赖
  • 必须将C#代码编译为动态库(输出文件后缀为.so),不能编译为可执行exe,否则ctypes无法定位导出的函数
  • 你之前遇到的“依赖不存在”报错,是因为照搬了Windows环境下基于第三方NuGet DllExport包的示例;在当前Mono环境下,完全不需要折腾NuGet拉取流程,系统源已提供所需的全部依赖

分步操作(完全匹配你当前的操作习惯,不需要额外学新工具)

1. 安装系统级依赖(替代NuGet拉包流程)

不需要手动找NuGet配置文件、不需要执行nuget restore,直接通过Ubuntu源安装现成的开发组件即可:

  • 执行命令:sudo apt install mono-devel mono-dll-export
  • 安装完成后,代码中用到的导出属性就已经在全局可用,不需要在项目目录下放任何依赖文件

2. 编写C#功能代码

新建一个名为MathLib.cs的文件,写入如下代码,不需要额外引用本地依赖文件:

using System;
using System.Runtime.InteropServices;
using Mono.DllExport;

namespace SampleLib
{
    public class NativeMethods
    {
        // 导出整数参数计算函数,调用约定和C++默认Cdecl对齐,避免传参错位
        [DllExport("AddIntegers", CallingConvention = CallingConvention.Cdecl)]
        public static int Add(int a, int b)
        {
            return a + b;
        }

        // 导出字符串处理函数,测试非数值类型参数传递
        [DllExport("GetStringLength", CallingConvention = CallingConvention.Cdecl)]
        public static int CalcStringLength(string input)
        {
            if (input == null) return -1;
            return input.Length;
        }
    }
}

3. 编译生成动态库

你之前用csc编译exe的逻辑不需要变,只需要加两个编译参数,和之前的操作没有本质区别:

  • 加-target:library:指定csc生成动态库,而非可执行exe
  • 加-out:libmathlib.so:指定输出文件后缀为.so,和C++编译的动态库格式完全兼容
  • 加-r:Mono.DllExport:告诉编译器引入全局安装的导出属性组件
    完整编译命令:
csc -target:library -out:libmathlib.so -r:Mono.DllExport MathLib.cs

编译完成后,当前目录下会生成libmathlib.so文件,这就是可以被ctypes直接加载的动态库,和你之前用g编译的C so没有使用差异。

4. Python侧调用

Python侧的代码和你之前调用C++动态库的逻辑完全一致,不需要额外安装第三方包:

import ctypes

# 加载动态库,操作和加载C++编译的so无区别
lib = ctypes.CDLL("./libmathlib.so")

# 配置整数函数的参数和返回值类型
lib.AddIntegers.restype = ctypes.c_int
lib.AddIntegers.argtypes = [ctypes.c_int, ctypes.c_int]
calc_result = lib.AddIntegers(12, 23)
print(f"整数计算结果:{calc_result}")  # 输出35

# 配置字符串函数的参数和返回值类型
lib.GetStringLength.restype = ctypes.c_int
lib.GetStringLength.argtypes = [ctypes.c_char_p]
str_len = lib.GetStringLength(b"test csharp dll")
print(f"字符串长度:{str_len}")  # 输出15

常见操作问题

  • 运行时需要手动用mono启动动态库吗?
    不需要。编译生成的so已经内嵌了必要的Mono运行时逻辑,Python加载时会自动完成初始化,和C++动态库的加载流程完全一致,不需要手动敲mono命令
  • 为什么我之前直接抄NuGet版的示例代码会报错?
    Windows环境下的DllExport是第三方NuGet包,需要手动在项目中引入依赖;但你当前的Mono环境对应的导出功能是系统预装组件,没有引入第三方NuGet的必要,照搬Windows的示例会因为缺少NuGet缓存的依赖文件触发报错
  • 能不能直接用编译好的exe让Python调用?
    不能。exe是可执行格式,没有对外暴露的导出函数表,ctypes无法定位到里面写的方法;只有编译为带导出表的动态库,才能实现和C++ extern方案一样的调用体验

内容的提问来源于stack exchange,提问作者Ri Di

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 07:45:07