我正在尝试使用 CMAKE 在 nodejs 中构建一个插件。CPP 文件有一个由我在 CSharp 中创建的非常基本的依赖项,这是一个必须从 CPP 调用的类。当我在使用 Visual Studio 编译的 CPP 控制台应用程序中执行此操作时,一切正常。当我使用 CMAKE-JS 进行编译以创建节点插件时,问题就出现了,当它必须调用我在 Csharp 中创建的程序集 dll 中的方法时,它告诉我找不到指定的文件。
这是我在 CSharp 中的类库,它输出一个名为 writeText.dll 的文件(框架版本 4.8)
写文本.cs
using System;
using System.Linq;
namespace writeText
{
public class CsTemplate
{
public string string1;
public string string2;
private static CsTemplate oInstance;
public CsTemplate()
{
}
/**
* @method Instance
*
* Singleton
*
* @returns {CsRecognizer} Clase instanciada.
*/
public static CsTemplate Instance()
{
if (oInstance == null)
{
oInstance = new CsTemplate();
}
return oInstance;
}
/**
* @method setString
*
* Asign values to properties
*
* @returns {CsRecognizer} Clase instanciada.
*/
public string setString(string str1, string str2)
{
string1 = str1;
string2 = str2;
return "El se asigna como " + string1 + " y la gramática se asignaa como " + string2;
}
}
}
这是利用 Csharp 中创建的依赖项的 Cpp 文件
主文件
#include <node_api.h>
#include <assert.h>
using namespace writeText;
namespace myaddon
{
#pragma managed
void callManaged()
{
System::String^ result = gcnew System::String("hello");
System::Console::WriteLine("It works: " + result);
}
void CallCsharp()
{
System::String^ str1Cpp = gcnew System::String("Uno");
System::String^ str2Cpp = gcnew System::String("Dos");
System::Console::WriteLine("String definidos: " + str1Cpp + " -> " + str2Cpp);
CsTemplate::Instance()->setString(str1Cpp, str2Cpp);
}
void printResults() {
System::Console::WriteLine("Defined strings: " + CsTemplate::Instance()->string1 + " -> " + CsTemplate::Instance()->string2);
}
#pragma unmanaged
napi_value Test(napi_env env, napi_callback_info info) {
napi_status status;
napi_value response;
callManaged();
status = napi_create_string_utf8(env, "OK", NAPI_AUTO_LENGTH, &response);
assert(status == napi_ok);
return response;
};
napi_value SetStrings(napi_env env, napi_callback_info info) {
napi_status status;
napi_value response;
CallCsharp();
status = napi_create_string_utf8(env, "OK", NAPI_AUTO_LENGTH, &response);
assert(status == napi_ok);
return response;
};
napi_value PrintStrings(napi_env env, napi_callback_info info) {
napi_status status;
napi_value response;
printResults();
status = napi_create_string_utf8(env, "OK", NAPI_AUTO_LENGTH, &response);
assert(status == napi_ok);
return response;
};
#define DECLARE_NAPI_METHOD(name, func) { name, 0, func, 0, 0, 0, napi_default, 0 }
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor listen = DECLARE_NAPI_METHOD("test", Test);
status = napi_define_properties(env, exports, 1, &listen);
assert(status == napi_ok);
napi_property_descriptor set = DECLARE_NAPI_METHOD("set", SetStrings);
status = napi_define_properties(env, exports, 1, &set);
assert(status == napi_ok);
napi_property_descriptor print = DECLARE_NAPI_METHOD("print", PrintStrings);
status = napi_define_properties(env, exports, 1, &print);
assert(status == napi_ok);
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
}
这是我的 CmakeLists.txt,它编译了 nodejs 插件
CmakeLists.txt
cmake_minimum_required(VERSION 3.17)
project (my-addon CXX CSharp)
include_directories(${CMAKE_JS_INC})
file(GLOB SOURCE_FILES "src/*.cpp")
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
target_compile_options(${PROJECT_NAME} PRIVATE /clr)
target_compile_options(${PROJECT_NAME} PRIVATE /fp:precise) #/fp:strict is incompatible with /clr
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_ROOTNAMESPACE ${PROJECT_NAME})
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_KEYWORD "ManagedCProj")
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_CLRSupport "true")
set_property(TARGET ${PROJECT_NAME} PROPERTY DOTNET_TARGET_FRAMEWORK_VERSION "4.8")
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_GLOBAL_WindowsTargetPlatformVersion "10.0.18362.0")
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DOTNET_REFERENCES_COPY_LOCAL "true")
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DOTNET_REFERENCES
"System"
)
# Add reference writeText.dll (This dll is writeText.cs compiled)
set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DOTNET_REFERENCE_writeText "src/writeText.dll")
set_target_properties(${PROJECT_NAME} PROPERTIES
PREFIX ""
SUFFIX ".node"
COMMON_LANGUAGE_RUNTIME ""
)
target_include_directories(${PROJECT_NAME}
PRIVATE ${CMAKE_SOURCE_DIR}/node_modules/node-addon-api
PRIVATE ${CMAKE_JS_INC})
target_link_libraries(${PROJECT_NAME}
PUBLIC
${CMAKE_JS_LIB}
)
完成后,一切都完美编译,生成/发布文件夹如下:
一切似乎都是正确的,插件被完美地创建,并且 writeText.dll 按预期复制到 build / Release 文件夹中。
然后我使用插件
main.js
var addon = require('bindings')('my-addon');
console.log("Test: " + addon.test());
console.log("Set: " + addon.set());
console.log("Print: " + addon.print());
我明白了
$ node main.js
It works: hello
Test: OK
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or
assembly 'writeText, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system could not find especified file
on myaddon.CallCsharp()
在测试方法调用中,一切正常,并使用 System 命名空间完美地打印到我的屏幕上,但是当调用使用我的 writeText.dll 的set方法时,它告诉我找不到文件。
正如您在输出结构的图像中看到的那样,文件就在那里。此外,当我在 Visual Studio 中打开由 CMake 创建的项目时,程序集似乎是正确的。
这是Cmake构建的项目的结构:
一切似乎都是正确的,原则上它应该可以正常工作,但由于某种原因,它告诉我无法找到 writeText。