我已经在这个话题上挣扎了一周,但我try 的任何东西似乎都没有奏效. 我创建了一个非常简单的C#类:
namespace SimpleMathLib
{
public class SimpleMath
{
public float SumFloat(float a, float b)
{
return a + b;
}
public int SumInt(int a, int b)
{
return a + b;
}
}
}
in a Visual Studio 2022 solution configured to build a DLL:
我确实阅读了一些在线教程,但给我带来的问题较少的是关于创建使用CLR的C++包装器并将其编译为静态库(.lib)的教程. 下面是我在这个包装器中添加的脚本:
// SimpleMathLibWrapper.h
#pragma once
class SimpleMathLibWrapperPrivate;
class __declspec(dllexport) SimpleMathLibWrapper
{
private:
SimpleMathLibWrapperPrivate* _private;
public:
SimpleMathLibWrapper();
~SimpleMathLibWrapper();
float SumFloat(const float a, const float b);
int SumInt(const int a, const int b);
};
// SimpleMathLibWrapper.cpp
#include "..\public\SimpleMathLibWrapper.h"
#include <msclr\auto_gcroot.h>
#include <msclr\marshal_cppstd.h>
using namespace System::Runtime::InteropServices;
using namespace SimpleMathLib;
class SimpleMathLibWrapperPrivate
{
public:
msclr::auto_gcroot<SimpleMath^> simpleMathCSharp;
};
SimpleMathLibWrapper::SimpleMathLibWrapper()
{
_private = new SimpleMathLibWrapperPrivate();
_private->simpleMathCSharp = gcnew SimpleMath();
}
SimpleMathLibWrapper::~SimpleMathLibWrapper()
{
delete _private;
}
float SimpleMathLibWrapper::SumFloat(const float a, const float b)
{
return _private->simpleMathCSharp->SumFloat(a, b);
}
int SimpleMathLibWrapper::SumInt(const int a, const int b)
{
return _private->simpleMathCSharp->SumInt(a, b);
}
and these are the settings of the Visual Studio CLR library project I had to change: moreover, I added the compiled C# DLL reference to the project
现在,对于C++可执行项目,它是一个带有以下脚本的Visual Studio C++控制台项目:
// SimpleMathLibUser.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
//#define LOAD_DLL_MANUALLY
#include <iostream>
#include <Windows.h>
#ifndef LOAD_DLL_MANUALLY
#include "SimpleMathLibWrapper.h"
#endif // !LOAD_DLL_MANUALLY
#ifdef LOAD_DLL_MANUALLY
void PrintExecutablePath()
{
TCHAR exePath[MAX_PATH];
GetModuleFileName(NULL, exePath, MAX_PATH);
char narrowExePath[MAX_PATH];
// convert the string to a narrow character string
if (WideCharToMultiByte(CP_ACP, 0, exePath, -1, narrowExePath, MAX_PATH, 0, 0) == 0)
{
std::cerr << "Failed to convert the path to a narrow character string." << std::endl;
return;
}
char* lastSlash = strrchr(narrowExePath, '\\');
if (lastSlash != NULL)
{
*lastSlash = '\0';
}
std::cout << "Current directory: " << narrowExePath << std::endl << std::endl;
}
#endif // LOAD_DLL_MANUALLY
int main()
{
#ifdef LOAD_DLL_MANUALLY
PrintExecutablePath();
// load the DLL.
HMODULE mathLib = LoadLibrary(TEXT("..\\Plugins\\SimpleMathLibWrapper.dll"));
if (mathLib == NULL)
{
std::cerr << "Failed to load the DLL." << std::endl;
return 1;
}
// get a pointer to functions from the DLL.
float (*SumFloat)(float, float) = (float (*)(const float, const float))GetProcAddress(mathLib, "SumFloat");
int (*SumInt)(int, int) = (int (*)(const int, const int))GetProcAddress(mathLib, "SumInt");
if (SumFloat == NULL)
{
std::cerr << "Failed to find the 'SumFloat' function in the DLL." << std::endl;
return 1;
}
if (SumInt == NULL)
{
std::cerr << "Failed to find the 'SumInt' function in the DLL." << std::endl;
return 1;
}
// call the functions.
float resultFloat = SumFloat(10.f, 5.f);
std::cout << "Float Sum: " << resultFloat << std::endl;
int resultInt = SumInt(2, 3);
std::cout << "Int Sum: " << resultInt << std::endl;
// unload the DLL.
FreeLibrary(mathLib);
#else
SimpleMathLibWrapper wrapper;
std::cout << "Float Sum: " << wrapper.SumFloat(10.f, 5.f) << std::endl;
std::cout << "Int Sum: " << wrapper.SumInt(2, 3) << std::endl;
#endif // LOAD_DLL_MANUALLY
return 0;
}
如你所见,为此,我try 了两种方法:
- 手动加载包装器
- 使用链接器
These are the settings I added for the linker solution (which is currently the one that at least compile and seems to work until a certain point):
C#DLL是用哪个.NET版本编译的并不重要,当我运行可执行文件时,我总是得到以下错误:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. Impossible to find the scpecified file.
in SimpleMathLibWrapper.{ctor}(SimpleMathLibWrapper* )
in mainCRTStartup()
我所知道的是.NET版本的Runtime和SDK都已安装并在系统中正确引用. 无论我在C#VS项目中 Select 目标框架的哪个版本,结果都是相同的;只是程序集名称和版本发生了变化.
我也在互联网上寻找这个特定的问题,但大多数解决方案都是try 直接从.sln文件而不是从VS打开项目,这对我不起作用.
手动加载DLL会导致一系列我无法解决的不同问题,因此,我保留了代码以供参考,但放弃了try 修复它.
我知道这是一篇很长的帖子,我鼓励你问我更多的细节,以防我遗漏了什么. 希望在这里找到解决方案将能够在future 帮助更多的人.
谢谢!!