无法从 C# 访问的 C++ 包装方法
C++ wrapped methods inaccessible from C#
我有一个用 C++ 编写的静态库,我想通过我的 C# 程序访问它。该库包含多个 classes。在我的研究和工作中,我为静态库开发了一个 CLR DLL 包装器来访问 class 方法(打开和关闭)。在我尝试从 DLL 调用 'public' 函数之一之前,一切都成功了。我在尝试编译 C# 项目时收到 f(x)
is unaccessible due to its protection level。 f(x)
在这种情况下指向 JsonMsgClientDll.jmcDll.jmClientClose()
和 JsonMsgClientDll.jmcDll.jmcOpen()
。我搜索了其他破布,没有找到与我遇到的类似的东西。这里的任何帮助都会很棒。请注意,在静态库的多个 classes 中,我只是尝试移植(包装)最基本的 (open/close) 函数以使其首先运行。一切都已完成 public,因此无法弄清楚为什么无法访问它们。
我在下面列出了必要的代码片段。 jsonmsgservice
命名空间是静态库引用,其中 class 是 JsonMsgClient
。 jmcDLL.cpp
的输出是一个名为 JsonMsgClientDll.dll
的 DLL。注意到的 DLL 在 C# 项目中被正确引用。
jmcDLL.cpp
#include <vcclr.h>
#include "JmsClientConnector.h"
#include "JmsStatus.h"
#include "JsonMsgClient.h"
using namespace System;
using namespace jsonmsgservice;
namespace JsonMsgClientDll
{
public ref class jmcDll
{
public:
// constructor
jmcDll()
{
_myJsonMsgClient = new JsonMsgClient();
}
// destructor
~jmcDll()
{
delete _myJsonMsgClient;
}
// open a connection
JmsStatus::JsonMsgStatus jmcOpen(string ipAddr)
{
return _myJsonMsgClient->SessionOpen(ipAddr);
}
// close a connection
JmsStatus::JsonMsgStatus jmClientClose()
{
return _myJsonMsgClient->SessionClose();
}
private:
JsonMsgClient * _myJsonMsgClient;
};
}
C# 主Window.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.IO.Ports;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using JsonMsgClientDll;
namespace JTC_GUI
{
public partial class MainWindow : Window
{
...
int sockFd = 0;
string ipAddress = "";
uint msgIdVal = 0;
jmcDll jmClient = new jmcDll();
public MainWindow()
{
...
}
private void clientOpenButton_Click(object sender, RoutedEventArgs e)
{
ipAddress = ipAddrInput.Text;
if (...)
...
else
{
// attempting to call wrappered C++ code to open a connection
int jmcStatus = jmClient.jmcOpen(ipAddress);
if (sockFd > 0)
{
...
private void clientCloseButton_Click(object sender, RoutedEventArgs e)
{
if (jmClient.jmClientClose() == 0)
{
...
}
else
{
MessageBox.Show("The connection FAILED to close or was never opened");
}
}
在 C++/CLI 代码中:
JmsStatus::JsonMsgStatus jmcOpen(string ipAddr)
{
return _myJsonMsgClient->SessionOpen(ipAddr);
}
函数参数的类型是string,是C++原生类型,而在你的C#代码中,你调用这个函数的参数是System.String,是引用类型,所以需要转换在这里完成。
函数应该是这样的:(假设你使用的是 std)
#include <msclr\marshal_cppstd.h>
JmsStatus::JsonMsgStatus jmcOpen(System::String^ ipAddr)
{
std::string unmanaged = msclr::interop::marshal_as<std::string>(ipAddr);
return _myJsonMsgClient->SessionOpen(unmanaged );
}
我有一个用 C++ 编写的静态库,我想通过我的 C# 程序访问它。该库包含多个 classes。在我的研究和工作中,我为静态库开发了一个 CLR DLL 包装器来访问 class 方法(打开和关闭)。在我尝试从 DLL 调用 'public' 函数之一之前,一切都成功了。我在尝试编译 C# 项目时收到 f(x)
is unaccessible due to its protection level。 f(x)
在这种情况下指向 JsonMsgClientDll.jmcDll.jmClientClose()
和 JsonMsgClientDll.jmcDll.jmcOpen()
。我搜索了其他破布,没有找到与我遇到的类似的东西。这里的任何帮助都会很棒。请注意,在静态库的多个 classes 中,我只是尝试移植(包装)最基本的 (open/close) 函数以使其首先运行。一切都已完成 public,因此无法弄清楚为什么无法访问它们。
我在下面列出了必要的代码片段。 jsonmsgservice
命名空间是静态库引用,其中 class 是 JsonMsgClient
。 jmcDLL.cpp
的输出是一个名为 JsonMsgClientDll.dll
的 DLL。注意到的 DLL 在 C# 项目中被正确引用。
jmcDLL.cpp
#include <vcclr.h>
#include "JmsClientConnector.h"
#include "JmsStatus.h"
#include "JsonMsgClient.h"
using namespace System;
using namespace jsonmsgservice;
namespace JsonMsgClientDll
{
public ref class jmcDll
{
public:
// constructor
jmcDll()
{
_myJsonMsgClient = new JsonMsgClient();
}
// destructor
~jmcDll()
{
delete _myJsonMsgClient;
}
// open a connection
JmsStatus::JsonMsgStatus jmcOpen(string ipAddr)
{
return _myJsonMsgClient->SessionOpen(ipAddr);
}
// close a connection
JmsStatus::JsonMsgStatus jmClientClose()
{
return _myJsonMsgClient->SessionClose();
}
private:
JsonMsgClient * _myJsonMsgClient;
};
}
C# 主Window.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.IO.Ports;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using JsonMsgClientDll;
namespace JTC_GUI
{
public partial class MainWindow : Window
{
...
int sockFd = 0;
string ipAddress = "";
uint msgIdVal = 0;
jmcDll jmClient = new jmcDll();
public MainWindow()
{
...
}
private void clientOpenButton_Click(object sender, RoutedEventArgs e)
{
ipAddress = ipAddrInput.Text;
if (...)
...
else
{
// attempting to call wrappered C++ code to open a connection
int jmcStatus = jmClient.jmcOpen(ipAddress);
if (sockFd > 0)
{
...
private void clientCloseButton_Click(object sender, RoutedEventArgs e)
{
if (jmClient.jmClientClose() == 0)
{
...
}
else
{
MessageBox.Show("The connection FAILED to close or was never opened");
}
}
在 C++/CLI 代码中:
JmsStatus::JsonMsgStatus jmcOpen(string ipAddr)
{
return _myJsonMsgClient->SessionOpen(ipAddr);
}
函数参数的类型是string,是C++原生类型,而在你的C#代码中,你调用这个函数的参数是System.String,是引用类型,所以需要转换在这里完成。
函数应该是这样的:(假设你使用的是 std)
#include <msclr\marshal_cppstd.h>
JmsStatus::JsonMsgStatus jmcOpen(System::String^ ipAddr)
{
std::string unmanaged = msclr::interop::marshal_as<std::string>(ipAddr);
return _myJsonMsgClient->SessionOpen(unmanaged );
}