C++/CLI 包装器实现错误

Posted

技术标签:

【中文标题】C++/CLI 包装器实现错误【英文标题】:C++/CLI Wrapper Implementation Errors 【发布时间】:2020-03-25 07:52:22 【问题描述】:

我一直在尝试使用以下链接中的 C++/CLI 包装方案。

注意:在我上周进行的所有搜索中,以下项目是最常被引用为提供可行解决方案的项目。http://pragmateek.com/using-c-from-native-c-with-the-help-of-ccli-v2/

以下项目是我尝试链接到接受 Win32 Dll 的第 3 方应用程序。 Hy 的目标是将 Win32 Dll 链接到托管 C# DLL,其中的函数应该更易于编写和维护。

但是,我不断遇到以下错误的变体。

Error   C2664   'std::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(std::initializer_list<_Elem>,const std::allocator<char> &)' : cannot convert argument 1 from 'System::String ^' to 'const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &' Main_interface  

Error (active)  E0415   no suitable constructor exists to convert from "System::String ^" to "std::basic_string<char, std::char_traits<char>, std::allocator<char>>"    Main_interface  

我的 C# 库:MainUtilities.dll

//Main_Utility.cs

public class MainUtilities

    public string GetRevision(string CurrentRev)
    
        return CurrentRev + "_rev";
    

Main_Interface.h

#pragma once

#define DLL_EXP extern "C" __declspec(dllexport)
DLL_EXP void GetRevision(char* data_in, char *data_out);

class QFUtilitiesWrapperPrivate;

#ifdef BUILDINGQFUTILITIES
#define DLL_EXP_WRAP __declspec(dllexport)
#else
#define DLL_EXP_WRAP __declspec(dllimport)
#endif

#include <string>

class DLL_EXP_WRAP QF_UtilitiesWrapper

private: static QFUtilitiesWrapperPrivate* _private;

public: QF_UtilitiesWrapper();

public: ~QF_UtilitiesWrapper();

public: static std::string GetRevisionFunc(const char* rev);

;

Main_Interface.cpp

#include "stdafx.h"
#include "Main_Interface.h"
#include <msclr\auto_gcroot.h>
#using "MainUtilities.dll"
using namespace System::Runtime::InteropServices; // Marshal


class QFUtilitiesWrapperPrivate

public: msclr::auto_gcroot<MainUtilities^> main_Utilities;
;

QF_UtilitiesWrapper::QF_UtilitiesWrapper()

    _private = new QFUtilitiesWrapperPrivate();
    _private->main_Utilities = gcnew MainUtilities();


DLL_EXP void GetRevision(char* data_in, char *data_out)

    std::string s_b = QF_UtilitiesWrapper::GetRevisionFunc(data_in);
    strcpy_s(data_out, 100, s_b.c_str());


std::string QF_UtilitiesWrapper::GetRevisionFunc(const char* data_in)

    return _private->main_Utilities->GetRevision(gcnew System::String(data_in));
 //** ERROR ^^^^^^  ** 

QF_UtilitiesWrapper::~QF_UtilitiesWrapper()

    delete _private;

请注意错误发生在:'GetRevisionFunc'


编辑:好的 - 我做了以下更改:

//Main_Interface.h

private:  QFUtilitiesWrapperPrivate* _private;  // no longer static
public: const char* GetRevisionFunc(const char* rev); //function now: const char*
//Main_Interface.cpp

DLL_EXP void GetRevision(char* data_in, char *data_out)

    data_out = QF_UtilitiesWrapper::GetRevisionFunc(data_in);
  // ** ERROR ^^^^^^^^^^ **


const char* QF_UtilitiesWrapper::GetRevisionFunc( char* rev) // now: const char*

    System::String^ managedCapi = _private->main_Utilities->GetRevision(gcnew System::String(rev));
    return (const char*)Marshal::StringToHGlobalAnsi(managedCapi).ToPointer();

现在我正在努力解决以下错误:

Error C2352 'QF_UtilitiesWrapper::GetRevisionFunc' : illegal call of non-static member function

Error (active) E0245 a nonstatic member reference must be relative to a specific object

【问题讨论】:

【参考方案1】:

你必须对类型进行编组,这不是在 C++/CLI 中为你完成的。你有一个System::String^,但你想把它作为std::string返回,所以你必须编组它:

std::string QF_UtilitiesWrapper::GetRevisionFunc(const char* data_in)

    auto str = _private->main_Utilities->GetRevision(gcnew System::String(data_in));
    return msclr::interop::marshal_as<std::string>(str);

欲了解更多详情,请查看the docs。

您的QF_UtilitiesWrapper 还持有_private 作为静态 成员,您可以在构造函数/析构函数中设置和删除它。这会泄漏内存并可能导致意外行为。

【讨论】:

谢谢。我添加了您的更改以及:#include "msclr\marshal_cppstd.h" 不幸的是,我收到了一些外部错误:错误 LNK2001 未解析的外部符号“私有:静态类 QFUtilitiesWrapperPrivate * QF_UtilitiesWrapper::_private”(?_private@QF_UtilitiesWrapper@ @0PAVQFUtilitiesWrapperPrivate@@A) Main_interface.obj - 错误 LNK2020 未解析令牌 (0A000437) "private: static class QFUtilitiesWrapperPrivate * QF_UtilitiesWrapper::_private" (?_private@QF_UtilitiesWrapper@@0PAVQFUtilitiesWrapperPrivate@@A) Main_interface.obj @jonno 请参阅 ***.com/questions/195207/… 我已经解决了外部错误并修改了“_private”的声明。请参阅上面的代码更改。但现在我正在尝试解决新的错误。

以上是关于C++/CLI 包装器实现错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 C++/CLI 包装器将二维数组从 C# 传递到非托管 C++

如何为非托管 c dll 创建 c++\cli 包装器

Visual Studio:C++\CLI 包装器程序集路径依赖问题

在Visual Studio 2010中将Native / C ++ DLL链接到托管C ++ / CLI包装器

调整 MFC dll 以在 C++/CLI 包装器中使用

通过 CLI 包装器在非托管 C++ 中使用 C#.NET Winform - 需要线程?