C++包装的方法无法从 C# 访问

本文关键字:访问 包装 方法 C++ | 更新日期: 2023-09-27 18:36:40

我有一个用C++编写的静态库,我想通过我的 C# 程序访问它。 此库包括多个类。 在我的研究和工作中,我为静态库开发了一个 CLR DLL 包装器来访问类方法(打开和关闭)。 一切都成功了,直到我尝试从 DLL 调用其中一个"公共"函数。 我收到f(x)在尝试编译 C# 项目时由于其保护级别而无法访问。 在这种情况下,f(x)指向 JsonMsgClientDll.jmcDll.jmClientClose()JsonMsgClientDll.jmcDll.jmcOpen() . 我搜索了其他破布,没有找到与我遇到的类似的东西。 这里的任何帮助都会很棒。 请注意,在静态库的多个类中,我只是尝试移植(包装器)最基本的(打开/关闭)函数以使其首先工作。 所有这些都是公开的,因此无法弄清楚为什么它们无法访问。

我在下面列出了必要的代码片段。 jsonmsgservice命名空间是静态库引用,其中类JsonMsgClientjmcDLL.cpp的输出是一个名为 JsonMsgClientDll.dll 的 DLL。 在 C# 项目中正确引用了记下的 DLL。

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# 主窗口.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++包装的方法无法从 C# 访问

在 C++/CLI 代码中:

      JmsStatus::JsonMsgStatus jmcOpen(string ipAddr)
        {
            return _myJsonMsgClient->SessionOpen(ipAddr);
        }

函数参数的类型为 string,这是一种本机C++类型,而在 C# 代码中,使用 System.String paramter 调用此函数,这是一种引用类型,因此需要在此处完成转换。

函数应该是这样的:(假设你使用的是 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 );
   }