简体   繁体   English

无法使用CLI层在非托管C ++代码中编译托管C#代码

[英]Unable to compile managed c# code within unmanaged c++ code using cli layer

I am doing a POC where I need to invoke ac# method from a c++ application. 我正在做一个POC,我需要从c ++应用程序调用ac#方法。 So I did the following: 所以我做了以下事情:

  1. Create ac# library. 创建ac#库。
  2. Create a c++/cli library wrapping the dll from step 1. 创建一个包装步骤1中的dll的c ++ / cli库。
  3. Creating a c++ library that would consume cli wrapper. 创建一个将消耗cli包装器的c ++库。
  4. Creating an unmanaged console application that would use c++ dll output from step 3. 创建将使用步骤3中的c ++ dll输出的非托管控制台应用程序。

Guys, I have done a lot of searches in last days but did not get any useful help. 伙计们,最近几天我做了很多搜索,但没有得到任何有用的帮助。

  1. Created the c# project with output: DotNetLogger.dll 创建具有输出的C#项目:DotNetLogger.dll
  2. Created the c++/cli project with output: CliLogger.dll Also referenced DotNetLogger.dll Also exported a method. 用输出创建了c ++ / cli项目:CliLogger.dll也引用了DotNetLogger.dll也导出了一个方法。
  3. Create C++ project with output CppLogger.dll and so on. 使用输出CppLogger.dll等创建C ++项目。

Also, C# project setting: v4.6.2 C++/CLI project settings: /CLR enabled with v4.6.2 C++ project setting: no /clr 另外,C#项目设置:v4.6.2 C ++ / CLI项目设置:/ CLR与v4.6.2 C ++项目设置一起启用:否/ clr

namespace DotNetLogger
{
    public class ManagedLogger
    {
        public void Ping()
        {
          //Do something
        }
    }
}

using namespace System;
using namespace DotNetLogger;

namespace CliLogger {
    public ref class LoggerBridge
    {
    public:
        ManagedLogger^ obj;
        LoggerBridge() {
            obj = gcnew ManagedLogger();
        }
        void Result() {
            return obj->Ping();
        }
    };
}

__declspec(dllexport) void AreYouThere() {
    CliLogger::LoggerBridge obj;
    return obj.Result();
}

#pragma once

#include "D:\Logger_POC_NoWorks\InteropLogger\CliLogger\CliLogger.h"

__declspec(dllimport) void AreYouThere();

class UnmanagedLogger {
public:
    void InvokeResult() {
        return AreYouThere();
    }
};


#include "pch.h"
#include <iostream>
#include "D:\Logger_POC_NoWorks\InteropLogger\CppLogger\CppLogger.h"


int main()
{
    UnmanagedLogger uLogger;
    uLogger.InvokeResult();
}

Expected Result: The console application shall build successfully in VS 2017. 预期结果:控制台应用程序将在VS 2017中成功构建。

But I am getting compiler errors; 但是我遇到了编译器错误;

  1. Warning C4273 'AreYouThere': inconsistent dll linkage ServiceCode d:\\logger_poc_noworks\\interoplogger\\cpplogger\\cpplogger.h 5

  2. Error C2871 'DotNetLogger': a namespace with this name does not exist ServiceCode d:\\logger_poc_noworks\\interoplogger\\clilogger\\clilogger.h 4

  3. Error C2039 'LoggerBridge': is not a member of 'CliLogger' ServiceCode d:\\logger_poc_noworks\\interoplogger\\clilogger\\clilogger.h 21

And many cascading errors. 以及许多级联错误。

I'm guessing your second block of code is clilogger.h ? 我猜您的第二段代码是clilogger.h吗?

You don't need to include cliLogger.h in your 3rd block of code as you are only using AreYouThere which you have already declared, this declaration also conflicts with the declaration from the header (hence the inconsistent dll linkage warning). 您不需要在第3个代码块中包含cliLogger.h ,因为您仅使用已经声明的AreYouThere ,该声明也与标头中的声明冲突(因此, inconsistent dll linkage警告inconsistent dll linkage )。 This header also contains CLI code which will produce errors in your pure c++ file (probably the cause of your 'LoggerBridge': is not a member of 'CliLogger' error). 此标头还包含CLI代码,它将在纯c ++文件中产生错误(可能是'LoggerBridge': is not a member of 'CliLogger'的原因'LoggerBridge': is not a member of 'CliLogger'错误'LoggerBridge': is not a member of 'CliLogger' )。

The #include directive is resolved by the pre-processor, which just is a pure text processor unaware of actual C++ (or C) semantics. #include指令由预处理器解析,该预处理器只是一个纯文本处理器,不了解实际的C ++(或C)语义。 So this piece of code 所以这段代码

#include "D:\Logger_POC_NoWorks\InteropLogger\CliLogger\CliLogger.h"

__declspec(dllimport) void AreYouThere();

class UnmanagedLogger { /* ... */ }

will result in 将导致

using namespace System;
using namespace DotNetLogger;

namespace CliLogger { /* ... */ }

__declspec(dllexport) void AreYouThere()
{
    CliLogger::LoggerBridge obj;
    return obj.Result();
}

__declspec(dllimport) void AreYouThere();

class UnmanagedLogger { /* ... */ }

being presented to compiler after pre-processing, which will result in two problems: 在进行预处理后呈现给编译器,这将导致两个问题:

  1. Unmanaged compiler still sees managed code (eg public ref class LoggerBridge , which is invalid in pure unmanaged C++). 非托管编译器仍然可以看到托管代码(例如, public ref class LoggerBridge ,在纯非托管C ++中是无效的)。
  2. You get the incompatible declaration of AreYouThere , first with dllexport , then second time with dllimport . 您将首先使用dllexport获得AreYouThere的不兼容声明,然后使用dllimport获得不兼容的声明。

So you need a separate header only containing unmanaged code and managing the import/export problem. 因此,您需要一个单独的标头,仅包含不受管的代码并管理导入/导出问题。

Typically, you'd have something like: 通常,您会遇到以下情况:

#ifdef INSIDE_MY_DLL_IMPLEMENTATION // invent up some better name yourself...
#define DLL_IMPORT __declspec(dllexport)
#else
#define DLL_IMPORT __declspec(dllimport)
#endif

DLL_IMPORT void areYouThere();

In referencing project, you'd just include the header then, inside DLL code, you'd have instead: 在引用项目时,您只需包含标头,然后在DLL代码内,您将拥有:

#define INSIDE_MY_DLL_IMPLEMENTATION // must precede, of course...
#include "new_interface_file.h"

Generalising now: You can use this pattern for any DLL, managed or purely unmanaged alike. 现在概括:您可以将这种模式用于任何DLL,无论是托管还是完全非托管的。 For the latter case, you could even consider different compilers (eg __attribute__((dllimport)) for GCC, although you might need some extra work as GCC attributes don't precede, but follow function declaration). 对于后一种情况,您甚至可以考虑使用GCC的不同编译器(例如__attribute__((dllimport)) ,尽管您可能需要做一些额外的工作,因为GCC属性不在之前,而是在函数声明之后。 Solely: different C++ implementations (compilers) most likely come with incompatible ABI, so you should fall back to a pure C interface if you plan multiple compiler compatibility: 唯一:不同的C ++实现(编译器)很可能带有不兼容的ABI,因此,如果您计划多个编译器兼容性,则应使用纯C接口:

#ifdef __cplusplus
extern "C"
{
#endif

// ...

#ifdef __cplusplus
}
#endif

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM