【发布时间】:2020-11-18 15:50:17
【问题描述】:
我一直在阅读此处的多个示例以及有关如何完成此操作的其他来源。最近,我关注了这个在多个其他类似问题中已链接到的具体示例。
https://dorodnic.com/blog/2014/12/10/calling-cpp-by-example/
但是,即使直接从 github 导入此项目,它仍然会在 C# 项目中出现错误,无法引用 C++ CLI 代码。 “找不到类型或命名空间(您是否缺少 using 指令或程序集引用)”。这是我在自己遵循其他示例时发现的相同错误。谁能向我解释为什么这会失败和/或建议修复它的步骤?
编辑:在此处添加代码以节省时间。
//Logic.h
#pragma once
namespace MeaningOfLife
{
namespace Cpp
{
// This is our native implementation
// It's marked with __declspec(dllexport)
// to be visible from outside the DLL boundaries
class __declspec(dllexport) Logic
{
public:
int Get() const; // That's where our code goes
};
}
}
//Logic.cpp
#include "Logic.h"
int MeaningOfLife::Cpp::Logic::Get() const
{
return 42; // Really, what else did you expect?
}
//Logic.h CLI
#pragma once
namespace MeaningOfLife
{
namespace Cpp
{
// First a Forward Declaration to Cpp::Logic class:
class Logic; // This allows us to mention it in this header file
// without actually including the native version of Logic.h
namespace CLI
{
// Next is the managed wrapper of Logic:
public ref class Logic
{
public:
// Managed wrappers are generally less concerned
// with copy constructors and operators, since .NET will
// not call them most of the time.
// The methods that do actually matter are:
// The constructor, the "destructor" and the finalizer
Logic();
~Logic();
!Logic();
int Get();
void Destroy();
static void InitializeLibrary(System::String^ path);
private:
// Pointer to our implementation
Cpp::Logic* _impl;
};
}
}
}
//Logic.cpp CLI
#include "Logic.h"
#include "..\MeaningOfLife.Cpp\Logic.h"
#include <string>
#include <Windows.h>
using namespace std;
MeaningOfLife::Cpp::CLI::Logic::Logic()
: _impl(new Cpp::Logic())
// Allocate some memory for the native implementation
{
}
int MeaningOfLife::Cpp::CLI::Logic::Get()
{
return _impl->Get(); // Call native Get
}
void MeaningOfLife::Cpp::CLI::Logic::Destroy()
{
if (_impl != nullptr)
{
delete _impl;
_impl = nullptr;
}
}
MeaningOfLife::Cpp::CLI::Logic::~Logic()
{
// C++ CLI compiler will automaticly make all ref classes implement IDisposable.
// The default implementation will invoke this method + call GC.SuspendFinalize.
Destroy(); // Clean-up any native resources
}
MeaningOfLife::Cpp::CLI::Logic::!Logic()
{
// This is the finalizer
// It's essentially a fail-safe, and will get called
// in case Logic was not used inside a using block.
Destroy(); // Clean-up any native resources
}
string ManagedStringToStdString(System::String^ str)
{
cli::array<unsigned char>^ bytes = System::Text::Encoding::ASCII->GetBytes(str);
pin_ptr<unsigned char> pinned = &bytes[0];
std::string nativeString((char*)pinned, bytes->Length);
return nativeString;
}
void MeaningOfLife::Cpp::CLI::Logic::InitializeLibrary(System::String^ path)
{
string nativePath = ManagedStringToStdString(path);
LoadLibrary(nativePath.c_str()); // Actually load the delayed library from specific location
}
//C#
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace MeaningOfLife.WPF
{
using Cpp.CLI;
using Microsoft.Win32;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var fileOpenDialog = new OpenFileDialog
{
CheckFileExists = true,
Filter = "Native Library|MeaningOfLife.Cpp.dll",
InitialDirectory = Environment.CurrentDirectory
};
var result = fileOpenDialog.ShowDialog(this);
if (result.HasValue && result.Value)
{
Logic.InitializeLibrary(fileOpenDialog.FileName);
using (var wrapper = new Logic())
{
MessageBox.Show("The answer is " + wrapper.Get());
}
}
}
}
}
错误发生在使用 Cpp.CLI 时,然后在调用 Logic 时发生。
作为跟进,我也尝试了这个示例,并在代码的可比较位置收到了相同的错误。
https://www.red-gate.com/simple-talk/dotnet/net-development/creating-ccli-wrapper/
【问题讨论】:
-
您的 CLI 包装类将输出您需要在托管 C# 类中引用的程序集。根据错误,您似乎没有引用程序集。
-
对,我认为我做得对。我会用一些代码更新它以节省时间。谢谢。
-
您缺少 using 指令或程序集引用。前者是该网页最明显的原因,MainWindow.cs 缺少让编译器识别 Logic 类所需的 using 指令。它需要
using MeaningOfLife.Cpp.CLI;才能正确编译。或者其他方式,拼写全名:var wrapper = new MeaningOfLife.Cpp.CLI.Logic() -
MeaningOfLife 只给了我
MeaningOfLife.WPF的选项。MeaningOfLife.Cpp无法识别。 C# 有 CLI 作为参考,我认为这会更正,但情况似乎并非如此。 -
您可能会更轻松地使用
#pragma unmanaged,而不是为 cpp/cli 类使用两个单独的程序集:docs.microsoft.com/en-us/cpp/preprocessor/…