![](/img/trans.png)
[英]passing 2D array from C# to unmanaged C++ using C++/CLI wrapper
[英]C# calling unmanaged C++ using CLI wrapper
我一直在閱讀這里和其他來源的多個示例,了解如何實現這一點。 最近我關注了這個特定的例子,它與多個其他類似的問題相關聯。
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());
}
}
}
}
}
錯誤發生在 using Cpp.CLI 上,然后在調用 Logic 時發生。
作為跟進,我也嘗試了這個示例,並在代碼中的可比較位置收到了相同的錯誤。
https://www.red-gate.com/simple-talk/dotnet/net-development/creating-ccli-wrapper/
這是通過以下方式解決的:
A) 刪除並添加回應用程序的 WPF 部分
B) 將 CLI 引用的“Copy Local”屬性設置為 true。
由於缺乏知識,我遵循這些示例的原因是為了更多地了解此過程。 我不認為這是真正的答案,但它確實解決了我眼前的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.