Ширина аддона NodeJs C++/CLI и сборка C# Я не могу запустить его
Я пытаюсь создать надстройку в nodejs с помощью CMAKE. Файл CPP имеет очень простую зависимость, созданную мной в CSharp, классе, который должен вызываться из CPP. Когда я выполняю эту операцию в консольном приложении CPP, скомпилированном с помощью Visual Studio, все работает правильно. Проблема возникает, когда я выполняю компиляцию с помощью CMAKE-JS для создания надстройки узла, а затем, когда он должен вызвать метод, который находится в сборке dll, которую я создал в Csharp, он сообщает мне, что указанный файл не найден.
Это моя библиотека классов в CSharp, которая выводит файл с именем writeText.dll (Framework Version 4.8).
writeText.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;
}
}
}
Это файл Cpp, который использует зависимость, созданную в Csharp
main.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}
)
Как только это будет сделано, все будет отлично компилироваться, в результате чего появится следующая папка build/Release:
Вроде все правильно, аддон создан отлично и 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, но когда вызывается метод set, который использует мой writeText.dll, он сообщает мне, что файл не может быть найден.
Как вы можете видеть на изображении выходной структуры, файл есть. Кроме того, когда я открываю проект, созданный CMake в Visual Studio, сборка кажется правильной.
Это структура проекта, построенного Cmake:
Кажется, все правильно и в принципе должно работать нормально, но почему-то сообщает мне, что writeText не может быть найден.