1

我正在尝试使用 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构建的项目的结构:

项目 Cmake 结构

一切似乎都是正确的,原则上它应该可以正常工作,但由于某种原因,它告诉我无法找到 writeText。

4

0 回答 0