如何将C++CLI库链接到C++应用中?

问题描述 投票:0回答:1

我做了一个C++CLI包装器,用于在C++应用程序中使用C# DLL。我使用Visual Studio来管理项目和管理依赖关系,并且我用这种方式让它工作。

但是当我使用CMake来链接Visual Studio为我建立的库时,我无法让它工作。

cmake_minimum_required (VERSION 3.12)

project(playground CXX)

SET(CMAKE_CXX_STANDARD 17)

set(PLAYGROUND_SOURCE_DIR ${CCMAKE_CURRENT_SOURCE_DIR})
set(PLAYGROUND_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})

set(PLAYGROUND_SRC
main.cpp)

add_executable(Playground ${PLAYGROUND_SRC} ${PLAYGROUND_HDR})

find_library(comm_dll CommWrapper Lib/CommDLL)

target_link_libraries(Playground PUBLIC
${comm_dll}
)

使用这种方法会得到一个 "未解决的外部符号错误"。我把.dll,.lib和.h文件放在同一个文件夹里。

c++ cmake c++-cli
1个回答
-1
投票

正如Hans Passant已经说过的那样:你必须将你的C++CLI代码编译成动态库,才能从一个未管理的应用程序中消耗它。CLIM管理的代码不能从不能驻留在静态库中运行。如果你把C++CLI库目标从静态库改成动态库,你就可以成功地编译你的非托管C++应用程序。

我的一个想法是:我认为你最好使用混合模式的C++CLI DLLs来使用托管功能--你将能够使你的消费者应用程序完全摆脱对CLR的引用。

Element类的这种混合模式Wrapper的Header应该是这样的。

#pragma once

#pragma unmanaged

#if defined(LIB_EXPORT)
#define DECLSPEC_CLASS __declspec(dllexport)
#else
#define DECLSPEC_CLASS __declspec(dllimport)
#endif

class ElementWrapperPrivate;

class __declspec(dllexport) ElementWrapper
{
private:
    ElementWrapperPrivate* helper;

public:
    ElementWrapper();
    ~ElementWrapper();
public:
    void ExecuteCommand();
};

而实现则是这样的

#include "ElementWrapper.h"
#pragma managed

#include "Element.h"
#include <msclr\auto_gcroot.h>

using namespace System::Runtime::InteropServices;

class ElementWrapperPrivate
{
public:
    msclr::auto_gcroot<Element^> elementInst;  // For Managed-to-Unmanaged marshalling
};

ElementWrapper::ElementWrapper()
{
    helper = new ElementWrapperPrivate();
    helper->elementInst = gcnew Element();
}

ElementWrapper::~ElementWrapper()
{
    delete helper;
}

void ElementWrapper::ExecuteCommand()
{
    helper->elementInst->ExecuteCommand();
}

然后只需将 Element.cpp + ElementWrapper.cpp 编译成 DLL,然后在你的非托管应用程序中使用 ElementWrapper.h。

© www.soinside.com 2019 - 2024. All rights reserved.