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

如何从C#项目生成供C++调用的.lib与.dll文件?

问题描述

我想在C++代码中调用C#生成的DNL.dll和DNL_MATLAB.dll中的所有方法与参数,但目前因缺少.lib文件无法实现——单独使用.dll似乎行不通。我已获取生成这些.dll的完整C#项目,它通过scriptcs和mono编译,在Windows10的Cygwin窗口中运行Makefile可成功生成目标.dll,但始终不会生成.lib文件。我尝试用dumpbin从.dll生成.lib但完全失败,以下是生成.dll的Makefile及部分C#代码,恳请帮助解决。

附:生成DLL的Makefile

.PHONY: clean generate ./bin/Release/DNL.dll

all: clean generate  ./bin/Release/DBL.dll ./bin/Release/DNL_MATLAB.dll

generate:  
    @cd doc; doxygen Doxyfile_DNL
    @rm -rf ./bin/data/xml
    @cd data && doxygen val_NET_doxygen_conf
    @mkdir -p ./var
    @rm -rf ./var/*
    scriptcs ./build/scripts/GenerateAPI.csx -- release/v5.1.0/ Release 0 val Single

./bin/bin/Release/DNL.dll: 
    mkdir -p ./bin/Release
    mkdir -p ./src/Source_GENERAL
    @rm -f ./src/Source_GENERAL/*.cs
    @cp -f ./src/auto*.cs ./src/Source_GENERAL
    @cp -f ./src/Api.cs ./src/Source_GENERAL
    @cp -f ./src/ErrorCodes.cs ./src/Source_GENERAL
    @cp -f ./src/Host.cs ./src/Source_GENERAL
    @cp -f ./src/IController.cs ./src/Source_GENERAL
    @cp -f ./src/Logger.cs ./src/Source_GENERAL
    @cp -f ./src/HelperFunctions.cs ./src/Source_GENERAL
    @cp -f ./src/Spi.cs ./src/Source_GENERAL
    @cp -f ./src/UUTBase.cs ./src/Source_GENERAL
    mcs ./src/Source_GENERAL/*.cs ./src/Controllers/*.cs -t:library -out:./bin/Release/DNL.dll -r:System.Net.Http -sdk:4.6.1
    @rm -f ./src/Source_GENERAL/*
    @rm -r ./src/Source_GENERAL

./bin/Release/DNL_MATLABl.dll: 
    mkdir -p ./bin/Release
    mkdir -p ./src/Source_MATLAB
    @rm -f ./src/Source_MATLAB/*.cs
    @cp -f ./src/mat*.cs ./src/Source_MATLAB
    @cp -f ./src/Api.cs ./src/Source_MATLAB
    @cp -f ./src/ErrorCodes.cs ./src/Source_MATLAB
    @cp -f ./src/Host.cs ./src/Source_MATLAB
    @cp -f ./src/IController.cs ./src/Source_MATLAB
    @cp -f ./src/Logger.cs ./src/Source_MATLAB
    @cp -f ./src/Spi.cs ./src/Source_MATLAB
    @cp -f ./src/HelperFunctions.cs ./src/Source_MATLAB
    @cp -f ./src/UUTBase.cs ./src/Source_MATLAB
    mcs ./src/Source_MATLAB/*.cs ./src/Controllers/*.cs -t:library -out:./bin/Release/DNL_MATLAB.dll -r:System.Net.Http -sdk:4.6.1
    @rm -f ./src/Source_MATLAB/*.cs
    @rm -r ./src/Source_MATLAB

./bin/Debug/DNL.dll:
    mkdir -p ./bin/Release
    @cp -f ./src/*.cs ./src/Source_GENERAL
    $(CC) ./src/Source_GENERAL/*.cs ./src/Controllers/*.cs -t:library -debug -out:$(BINDIR)/$(CONFIG)/ DNL.dll -r:System.Net.Http -sdk:4.6.1
    @rm -f ./src/Source_GENERAL/*.cs

./bin/Debug/DNL_MATLAB.dll:
    mkdir -p ./bin/Release
    @cp -f ./src/*.cs ./src/Source_MATLAB
    mcs ./src/Source_MATLAB/*.cs ./src/Controllers/*.cs -t:library -debug -out:./bin/Release/DNL_MATLAB.dll -r:System.Net.Http -sdk:4.6.1
    @rm -f ./src/Source_MATLAB/*.cs

clean:
    @rm -rf doc/out/html
    @rm -rf doc/out/latex
    @rm -f ./src/auto*
    @rm -f ./src/mat*
    #@rm -rf ./bin/*
    @rm -rf ./src/Source_MATLAB
    @rm -rf ./src/Source_GENERAL

run: build
    @mono ./bin/app.exe

test: ./bin/Release/DNL.dll
    @rm -rf ./bin/Release/logs
    python3 ./test/python_test.py ./bin/Release/DNL.dll

hwtest: ./bin/Release/DNL.dll
    @rm -rf ./bin/Release/logs
    python3 ./test/python_hw_test.py ./bin/Release/DNL.dll

附:部分C#代码片段

using System;
using System.Collections.Generic;
namespace DNL
{
        public class _ADC12 : _module
    {
        static internal UInt32 myModuleAddress = 0x7;
        public class _PON : _register
        {
            static internal UInt32 myAddress = (myModuleAddress << 12) | 0x0;
            public _PON(_UUTBase _owner) : base(_owner, myAddress) {}
            public _spi F_PonLaunch {get => _owner.SpiProvider(myAddress, "PonLaunch");}
            public _spi F_Reserved0 {get => _owner.SpiProvider(myAddress, "Reserved0");}

        }
        public _PON R_PON { get { return new _PON(_owner); } }

        public class _CALIBRATION_STATUS : _register
        {
            static internal UInt32 myAddress = (myModuleAddress << 12) | 0x4;
            public _CALIBRATION_STATUS(_UUTBase _owner) : base(_owner, myAddress) {}
            public _spi F_CalibrationBusy {get => _owner.SpiProvider(myAddress, "CalibrationBusy");}
            public _spi F_CalibrationLaunchedOkay {get => _owner.SpiProvider(myAddress, "CalibrationLaunchedOkay");}
            public _spi F_Reserved0 {get => _owner.SpiProvider(myAddress, "Reserved0");}

        }
}
解决方案

首先要明确:你生成的是**.NET托管DLL**,不是原生C++的DLL,这类DLL没有原生DLL的导出表结构,所以不会自动生成.lib,dumpbin也无法从它生成可用的.lib。下面是几种可行的调用方案:

方案一:用C++/CLI做中间层

这是最通用的解决方案,适合调用整个C#类库的所有功能:

  • 创建C++/CLI类库项目,添加对DNL.dll的引用
  • 编写托管包装类,将C#中的类、方法、属性封装成原生C能识别的接口(比如用public ref class包装,暴露原生C可调用的函数)
  • 编译这个C++/CLI项目,会生成原生DLL和对应的.lib文件
  • 在你的原生C++项目中引用这个.lib和DLL,直接调用包装好的接口

方案二:给C#方法添加导出标记(P/Invoke)

如果只需要调用特定方法,可以给C#方法添加导出特性,让DLL生成原生导出表:

  • 在C#项目中安装UnmanagedExports NuGet包
  • 给需要导出的C#方法添加[DllExport]特性,指定导出名称和调用约定
  • 修改Makefile中的mcs编译命令,确保引用UnmanagedExports相关的程序集
  • 重新编译生成DLL后,用dumpbin /exports DNL.dll能看到导出的函数,此时可以用lib /def:DNL.def /out:DNL.lib生成.lib文件,然后在C++中用__declspec(dllimport)声明这些方法直接调用

方案三:使用COM互操作

将C#类库注册为COM组件,通过COM接口调用:

  • 在C#类上添加[ComVisible(true)]特性,确保类和方法对COM可见
  • 用regasm.exe工具注册DNL.dll(比如regasm /codebase DNL.dll)
  • 用tlbexp.exe生成类型库文件(.tlb)
  • 在C++项目中导入这个.tlb文件,通过COM对象的接口调用C#方法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:01:38