2

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");
            }
        }
DLeh
  • 23,806
  • 16
  • 84
  • 128
James Hall
  • 41
  • 5
  • what is the declaration of JmsStatus::JsonMsgStatus? Is it accessible from C#? – Matt Jan 06 '15 at 21:07
  • The status is an enum list. I do not believe it is accessible from the C# since buried in the original static lib, thus why I call the open/close and just look for an integer return. – James Hall Jan 06 '15 at 21:12
  • Then the return type of jmcOpen and jmcClose should be int as the enum is not accessible from C#. – Matt Jan 06 '15 at 21:15
  • Okay, tried that. Now the compiler is telling me that 'jmcOpen' is not supported by the language. What does that mean for the open call now? – James Hall Jan 06 '15 at 21:28

1 Answers1

1

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 );
   } 
Matt
  • 6,010
  • 25
  • 36
  • I tried your updates as noted, yet the inclusion of the opened up a ton of new 'errors' in ws2def.h, winsock2.h, ws2ipdef.h, etc. I am guessing my DLL is calling upon items with the static library thad conflict with adding this inclusion at this level. Kind of like the order in which Windows.h and Winsock.h are included cause problems. Any ideas to work around this without having to recreate the static library? – James Hall Jan 07 '15 at 14:38
  • Try this: http://stackoverflow.com/questions/17789807/converting-managed-systemstring-to-stdstring-in-c-cli; which doesn't require that header file. – Matt Jan 07 '15 at 15:04
  • That appears to work for me. Allow me to step through some code before officially closing this out. Thanks again for your responses. – James Hall Jan 07 '15 at 16:02
  • In that I have just been trying to get this all to compile, I tried to step into the C# program to see how the DLL calls flow. In doing this, I now get a "A first chance exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll" exception error to pop up before the first line of (C#) codes is exercised. In further investigation, if the line of "jmcDll jmClient = new jmcDll();" is removed (and other related calls to the wrapped DLL (jmcDLL), the exception goes away. Is something not setup correctly to utilize the wrapped DLL? – James Hall Jan 07 '15 at 17:12
  • Please check this: http://stackoverflow.com/questions/12509738/a-continued-saga-of-c-sharp-interoprability-with-unmanaged-c – Matt Jan 07 '15 at 17:18
  • That's not quite the same issue. Also, I created a wrapper DLL so that import/export would not be necessary. I simply get an exception at the point of actually using (new) the DLL class. Any other ideas? – James Hall Jan 07 '15 at 19:02
  • what is the exception? – Matt Jan 07 '15 at 19:03
  • It is stated above in the previous comment. The additional information states the following: 'The invocation of the constructor on type 'JsonTcGui.MainWindow' that matches the specified binding constraints threw an exception.' Line number '3' and line position '9'. – James Hall Jan 07 '15 at 19:35
  • Sorry, I don't know what this means. – Matt Jan 07 '15 at 20:29