James Hall
James Hall

Reputation: 41

C++ wrapped methods inaccessible from C#

I have a static library written in C++ that I wanted to access via my C# program. This library includes multiple classes. In my research and workings, I developed a CLR DLL wrapper for the static library to access the class methods (open and close). All successful until I tried to call one of the 'public' functions from the DLL. I receive the f(x) is inaccessible due to its protection level when trying to compile the C# project. f(x) in this case points to JsonMsgClientDll.jmcDll.jmClientClose() and JsonMsgClientDll.jmcDll.jmcOpen(). I have searched other rags to not find anything similar to what I have run into. Any help here would be great. Just a note that of the multiple classes of the static library, I am only trying to port (wrapper) the most basic (open/close) of functions to get it working firstly. All is made public and thus cannot figure out why they are not accessible.

I have listed the necessary code snippets below. The jsonmsgservice namespace is the static library reference where the class is JsonMsgClient. The output of the jmcDLL.cpp is a DLL named JsonMsgClientDll.dll. The noted DLL is referenced properly in the C# project.

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# Main 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");
            }
        }

Upvotes: 2

Views: 765

Answers (1)

Matt
Matt

Reputation: 6050

In the C++/CLI code:

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

The type of the function parameter is string, which is a native C++ type, while in your C# code, you call this function with a System.String paramter, which is a reference type, so the conversion need to be done here.

The function should be like this:(assuming you're using 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 );
   } 

Upvotes: 1

Related Questions