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

多命名空间SWIG接口文件同模块生成C# PINVOKE异常求助

问题描述

我有多个分属不同命名空间的C++文件及类,它们被编译为同一个DLL,希望通过SWIG接口生成对应的C# API。

C++源文件代码

FileCPP1.cpp

namespace First
{
    class MyClass1 {
    public:
        MyClass1() = default;
        void HelloWorld(const std::string& msg) { cout << "Hello World!" << msg << endl;}
    };
}

FileCPP2.cpp

namespace Second {
    class MyClass2 {
    public:
      MyClass2() = default;
      void HelloWorldAgain(const std::string& msg) { cout << "Hello World again!" << msg << endl;}
     };
}

我的尝试操作

MyClass1.i

%include "std_string.i"
%typemap(csclassmodifiers) First::MyClass1
namespace First {
    class MyClass1 {
      MyClass1();
      void HelloWorld(const std::string& msg);
    };
}

编译命令:

swig.exe -c++ -csharp -DSWIG2_CSHARP -outdir CSFolder -namespace First -module Base

MyClass2.i

%include "std_string.i"
%typemap(csclassmodifiers) Second::MyClass2
namespace Second{
    class MyClass2 {
      MyClass2();
      void HelloWorldAgain(const std::string& msg);
    };
}

编译命令:

swig.exe -c++ -csharp -DSWIG2_CSHARP -outdir CSFolder -namespace Second -module Base

Base.i

%module Base

%include "MyClass1.i"
%include "MyClass2.i"

编译命令:

swig.exe -c++ -csharp -DSWIG2_CSHARP -outdir CSFolder

我期望生成的BasePINVOKE.cs文件包含MyClass1和MyClass2的调用方法,但编译后仅随机出现其中一个类的调用方法,其余文件生成正常。将%include替换为%import后问题依旧,请问我哪里操作错误?


解决方案

问题出在两个核心错误:

  1. 单个.i文件的语法错误:%typemap(csclassmodifiers)的用法完全错了,你直接写了C#类定义,这不是SWIG的正确语法。这个typemap是用来指定生成的C#类的修饰符(比如public),而非直接定义类结构。

  2. 重复编译单个接口文件导致覆盖:你分别编译MyClass1.i和MyClass2.i,两次都会生成同名的BasePINVOKE.cs,后面的编译会直接覆盖前面的文件,所以最终只会保留最后一次编译的类的方法。

正确的做法是只用一个主接口文件统一处理所有类,无需单独编译单个.i文件。

正确的接口文件写法

Base.i

%module Base

// 引入std_string处理C++字符串到C#的映射
%include "std_string.i"

// 为First命名空间的类指定C#命名空间和类修饰符
%typemap(csnamespace) First::MyClass1 "First"
%typemap(csclassmodifiers) First::MyClass1 "public class"

// 告诉SWIG要包含的C++头文件,用于解析类定义
%{
#include "FileCPP1.h"
%}
// 声明要暴露的First命名空间类
namespace First {
    class MyClass1 {
    public:
        MyClass1() = default;
        void HelloWorld(const std::string& msg);
    };
}

// 为Second命名空间的类指定C#命名空间和类修饰符
%typemap(csnamespace) Second::MyClass2 "Second"
%typemap(csclassmodifiers) Second::MyClass2 "public class"

// 包含Second类的头文件
%{
#include "FileCPP2.h"
%}
// 声明要暴露的Second命名空间类
namespace Second {
    class MyClass2 {
    public:
      MyClass2() = default;
      void HelloWorldAgain(const std::string& msg);
    };
}

正确的编译命令

只需要运行一次SWIG编译主接口文件即可:

swig.exe -c++ -csharp -DSWIG2_CSHARP -outdir CSFolder -module Base

关键说明

  • %typemap(csnamespace)用来绑定C命名空间到对应的C#命名空间,保证生成的C#类结构和C一致。
  • %{ ... %}块必须包含对应C++类的头文件,否则SWIG无法解析类的定义。
  • 绝对不要单独编译单个类的.i文件,避免生成重复的PINVOKE文件互相覆盖。
  • 最后要确保所有C++源文件编译打包成同一个DLL,SWIG生成的C#代码会调用这个DLL的导出函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 04:47:16