DLL 从 C++ .so 转换而无法导入 Dll,因为“找不到入口点”

DLL converted from C++ .so unable to DllImport due to "Unable to find Entry Point"

提问人:user3613025 提问时间:10/31/2023 更新时间:10/31/2023 访问量:36

问:

目前我有一个遗留文件,这样当它在 .cs 文件中 -ed 并运行编译的 C# 文件时,C# 文件能够毫无问题地使用功能。bcl_engine_rule.soDllImportdotnet xxx.dll.so

现在,为了能够在Windows上调试C#程序,而不必每次都通过迁移到Linux环境来测试它,我已经费尽心思将文件转换为文件(也从头开始构建所有单独的依赖项到单独的.dll),以便我可以将其导入Windows。在遇到如此多的错误(我将在下面概述)之后,我决定将库的复杂性降低到最简单的程度,以至于我基本上导出了一个非常简单的函数,但相同的错误仍然存在,这意味着我可能错过了一些简单的东西。bcl_engine_rule.sobcl_engine_rule.dll

小型可重现库是这样的(剥离了很多东西):

Fix2Winner2
- src
  - RulesEngine
    - RuleEngine.cpp
    - RuleEngine.h
  - bcl_rule_engine.cpp
- CMakeLists.txt

规则引擎.h

#ifndef TESTRULEENGINE_H_
#define TESTRULEENGINE_H_

#include <string>

namespace Rules
{
class RuleEngine
{
public:
    RuleEngine();
    virtual ~RuleEngine();

    bool loadFromConfig(const std::string&);
    void setDebugMode ( int debug );

    static bool _debug;
    static bool getDebugMode() { return _debug; }

private:

};

}
#endif

规则引擎.cpp

#include "RuleEngine.h"
#include <iostream>

namespace Rules
{

bool RuleEngine::_debug = false;

RuleEngine::RuleEngine()
{
    std::cout << "Creating Test Rule Engine object " << std::endl;
}

void RuleEngine::setDebugMode( int debug )
{
    if ( debug > 0 )
    {
        _debug = true;
    }
    else
    {
        _debug = false;
    }

    std::cout << "*** Setting debug mode to " << _debug << std::endl;

}

RuleEngine::~RuleEngine()
{
    std::cout << "Destroying Test Rule Engine object " << std::endl;
}

}

bcl_rule_engine.cpp

#include "RulesEngine/RuleEngine.h"
#include <iostream>
#include <cstring>
using namespace Rules;

RuleEngine* ruleEngine=0;

extern "C"
{
int init_config_rule_engine( char* configFile, int debugMode)
{
    ruleEngine = new RuleEngine();  

    if ( !ruleEngine )
    {
        return -1;
    }

    ruleEngine->setDebugMode( debugMode );

    if ( !ruleEngine->loadFromConfig( configFile ) )
    {
        return -2;
    }

    if (ruleEngine)
    {
        delete ruleEngine;
        ruleEngine = 0;
    }

    return 0;
}
}

现在基本上是我尝试在我的 C# 代码上运行的函数之一。我省略了另一个,因为没有必要引入它来重现错误。init_config_rule_engine

我在Visual Studio中使用CMake来编译dll。这样做更容易,因为我只是重用用于构建旧 so 文件的 CMakeLists.txt(我没有写)。这是我的CMakeLists.txt

cmake_minimum_required( VERSION 2.4 )

PROJECT(Fix2Winner2)

SET ( ARCH ${CMAKE_SYSTEM_PROCESSOR} )
MESSAGE( "******  Machine is : ${ARCH}" )

SET(PROJECT_NAME "Fix2Winner2")

include_directories(
   C:/dev/Fix2Winner2/src
   C:/dev/Fix2Winner2/src/RulesEngine
)

link_directories(
)

SET ( LIB_RULES_SRC
    src/RulesEngine/RuleEngine.cpp
)

SET ( LIB_BCL_RULE_ENGINE_SRC
    src/bcl_rule_engine.cpp
)

add_definitions(  -Wall -D_XOPEN_SOURCE=500 -D_REENTRANT -D_THREAD_SAFE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE )

add_library( "fix2winner2_rules" STATIC ${LIB_RULES_SRC} )
add_library( "bcl_rule_engine" SHARED ${LIB_BCL_RULE_ENGINE_SRC} )

target_link_libraries( "bcl_rule_engine" "fix2winner2_rules" )

我还没有真正研究过这些编译标志的作用,但它们似乎没有引起任何问题。我当时在 VS 的 Developer PowerShell 上编译了它,并产生了以下输出cmake .cmake --build . --config Release

CMake is re-running because C:/dev/Fix2Winner2/CMakeFiles/generate.stamp is out-of-date.
  the file 'C:/dev/Fix2Winner2/CMakeLists.txt'
  is newer than 'C:/dev/Fix2Winner2/CMakeFiles/generate.stamp.depend'
  result='-1'
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
  Compatibility with CMake < 2.8.12 will be removed from a future version of
  CMake.

  Update the VERSION argument <min> value or use a ...<max> suffix to tell
  CMake that the project does not need compatibility with older versions.


-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.19044.
******  Machine is : AMD64
-- Configuring done (0.0s)
-- Generating done (0.1s)
-- Build files have been written to: C:/dev/Fix2Winner2
MSBuild version 17.7.2+d6990bcfa for .NET Framework

  Checking Build System
  Building Custom Rule C:/dev/Fix2Winner2/CMakeLists.txt
  RuleEngine.cpp

  Bunch-of-warnings-here...

  fix2winner2_rules.vcxproj -> C:\dev\Fix2Winner2\Release\fix2winner2_rules.lib
  Building Custom Rule C:/dev/Fix2Winner2/CMakeLists.txt
  bcl_rule_engine.vcxproj -> C:\dev\Fix2Winner2\Release\bcl_rule_engine.dll
  Building Custom Rule C:/dev/Fix2Winner2/CMakeLists.txt

乍一看,cmake 文件似乎正在编译两个库,然后将前者链接到后者。然而,在原始的 cmake 文件中,实际上被编译为 .我不得不将其更改为,否则MSVC编译器会抱怨找不到文件,使我无法构建dll。它基本上会显示错误fix2winner2_rulesbcl_rule_enginefix2winner2_rulesSHAREDSTATIC.lib

PS C:\dev\Fix2Winner2> cmake --build . --config Release
MSBuild version 17.7.2+d6990bcfa for .NET Framework

  fix2winner2_rules.vcxproj -> C:\dev\Fix2Winner2\Release\fix2winner2_rules.dll
  bcl_rule_engine.cpp

  Bunch-of-warnings-here...

LINK : fatal error LNK1181: cannot open input file 'Release\fix2winner2_rules.lib' [C:\dev\Fix2Winner2\bcl_rule_engine.vcxproj]

现在编译了 ,我是这样使用它的 Fix2Winner2Test.csbcl_rule_engine.dll

using System.Runtime.InteropServices;

class Program
{
    [DllImport(@"C:\\dev\\Fix2Winner2Test\\bcl_rule_engine.dll")] // @"C:\\dev\\Fix2WinnerCS\\Fix2Winner\\bcl_rule_engine.dll"
    private static extern bool init_config_rule_engine(string configFile, int debugMode);

    static void Main(string[] args)
    {
        Console.WriteLine("Hello, World!");

        init_config_rule_engine(@"C:\\dev\\t_equity_wprb_config_ajb.xml", 0);
    }
}

现在,如果我没有指定完整路径,即 它会给我一个错误DllImport("bcl_rule_engine.dll")

System.DllNotFoundException: 'Unable to load DLL 'bcl_rule_engine.dll' or one of its dependencies: The specified module could not be found. (0x8007007E)'

如果我确实包含完整路径,它会告诉我

System.EntryPointNotFoundException: 'Unable to find an entry point named 'init_config_rule_engine' in DLL 'C:\\dev\\Fix2Winner2Test\\bcl_rule_engine.dll'.'

无论我是否将 .fix2winner_rules.libbcl_rule_engine.dll

我在这里迷茫了。不知道如何从这里继续前进。起初我以为我的dll不正确,可能缺少一些依赖项。在线建议的 Dependency Walker 不支持 Windows 10,但我确实设法安装了 https://github.com/lucasg/Dependencies 并通过它运行了我的 dll。我不熟悉如何使用它,但它似乎并没有向我表明我错过了什么?

enter image description here

C# C++ .NET 函数 DLLIMPORT

评论

2赞 ChrisMM 10/31/2023
想必您正在使用 MSVC 进行编译?它是否真的为 C++ 项目生成了 .dll 和 .lib?没有,我不知道会不会......__declspec(dllexport)
0赞 PMF 10/31/2023
在依赖项查看器中,选择 dll (bcl_rule_engine.dll) 并查看输出的右侧。如果方法导出正确,您应该会在那里看到它。
0赞 drescherjm 10/31/2023
add_definitions( -Wall不是 MSVC 参数。-Wall
0赞 drescherjm 10/31/2023
默认情况下,在 msvc 中,如果您不告诉它这样做,它不会导出 dll 中的符号。此外,当没有导出的符号时,它不会创建导入库或 .exp 文件。
0赞 Osyotr 10/31/2023
MSVC 不会生成 .lib 文件,除非您至少有一个导出的函数。

答: 暂无答案