提问人:user3613025 提问时间:10/31/2023 更新时间:10/31/2023 访问量:36
DLL 从 C++ .so 转换而无法导入 Dll,因为“找不到入口点”
DLL converted from C++ .so unable to DllImport due to "Unable to find Entry Point"
问:
目前我有一个遗留文件,这样当它在 .cs 文件中 -ed 并运行编译的 C# 文件时,C# 文件能够毫无问题地使用功能。bcl_engine_rule.so
DllImport
dotnet xxx.dll
.so
现在,为了能够在Windows上调试C#程序,而不必每次都通过迁移到Linux环境来测试它,我已经费尽心思将文件转换为文件(也从头开始构建所有单独的依赖项到单独的.dll),以便我可以将其导入Windows。在遇到如此多的错误(我将在下面概述)之后,我决定将库的复杂性降低到最简单的程度,以至于我基本上导出了一个非常简单的函数,但相同的错误仍然存在,这意味着我可能错过了一些简单的东西。bcl_engine_rule.so
bcl_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_rules
bcl_rule_engine
fix2winner2_rules
SHARED
STATIC
.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.lib
bcl_rule_engine.dll
我在这里迷茫了。不知道如何从这里继续前进。起初我以为我的dll不正确,可能缺少一些依赖项。在线建议的 Dependency Walker 不支持 Windows 10,但我确实设法安装了 https://github.com/lucasg/Dependencies 并通过它运行了我的 dll。我不熟悉如何使用它,但它似乎并没有向我表明我错过了什么?
答: 暂无答案
评论
__declspec(dllexport)
add_definitions( -Wall
不是 MSVC 参数。-Wall