NodeJs аддон ширины C ++ / CLI и C# сборки не могу заставить его работать - PullRequest
1 голос
/ 21 марта 2020

Я пытаюсь создать аддон в nodejs, используя CMAKE. Файл CPP имеет очень базовую зависимость c, созданную мной в CSharp, классе, который должен вызываться из CPP. Когда я выполняю эту операцию в консольном приложении CPP, скомпилированном с Visual Studio, все работает правильно. Проблема возникает, когда я делаю компиляцию с CMAKE- JS, чтобы затем создать аддон узла, когда он должен вызвать метод в dll сборки, который я создал в Csharp, он говорит мне, что указанный файл не найден .


Это моя библиотека классов в CSharp, которая выводит файл с именем writeText.dll (Framework Framework 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 / Освободите папку следующим образом:

Сборка Struct / образ выпуска

Кажется, все правильно, аддон создан отлично, и 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() 

В test вызове метода все работает нормально и выводит на экран, используя пространство имен System, но когда вызывается метод set , использующий мой файл writeText.dll, он сообщает, что файл не найден.

Как вы можете видеть на изображении структуры вывода, файл там. Кроме того, когда я открываю проект, созданный CMake в Visual Studio, сборка кажется правильной.

Это структура проекта, созданного Cmake:

Project Cmake Struct

Кажется, все правильно, и в принципе все должно работать нормально, но по какой-то причине оно говорит мне, что writeText не может быть найден.

...