2015-01-06 6 views
2

У меня есть статическая библиотека, написанная на C++, которую я хотел получить через мою программу на C#. Эта библиотека включает в себя несколько классов. В своих исследованиях и разработках я разработал CLR DLL-оболочку для статической библиотеки для доступа к методам класса (открывать и закрывать). Все успешно, пока я не попытался вызвать одну из «публичных» функций из DLL. Я получаю f(x) недоступен из-за его уровня защиты при попытке скомпилировать проект C#. f(x) в этом случае указывает на JsonMsgClientDll.jmcDll.jmClientClose() и JsonMsgClientDll.jmcDll.jmcOpen(). Я искал другие тряпки, чтобы не найти ничего похожего на то, с чем я столкнулся. Любая помощь здесь была бы замечательной. Просто обратите внимание, что из нескольких классов статической библиотеки я пытаюсь только порт (wrapper) использовать самые основные функции (открывать/закрывать), чтобы заставить его работать в первую очередь. Все обнародовано и, следовательно, не может понять, почему они недоступны.C++ завернутые методы недоступны из C#

Я добавил необходимые фрагменты кода ниже. Пространство имен jsonmsgservice является ссылкой на статическую библиотеку, где класс JsonMsgClient. Вывод jmcDLL.cpp - это DLL с именем JsonMsgClientDll.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"); 
      } 
     } 
+0

что декларация JmsStatus :: JsonMsgStatus? Доступно ли это из C#? – Matt

+0

Статус - список перечислений. Я не верю, что он доступен из C#, поскольку он похоронен в исходном статическом lib, поэтому я называю open/close и просто ищу для целочисленного возврата. –

+0

Тогда возвращаемый тип jmcOpen и jmcClose должен быть int, поскольку перечисление недоступно из C#. – Matt

ответ

1

В коде C++/CLI:

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

типа параметр функции - это строка, которая является нативной C++, в то время как в коде C# вы вызываете эту функцию с параметром System.String, который является ссылочным типом, поэтому здесь нужно сделать преобразование.

Функция должна быть такой: (при условии, что вы используете станд)

#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); 
    } 
+0

Я пробовал ваши обновления, как отмечено, но включение открыло тонну новых «ошибок» в ws2def.h, winsock2.h, ws2ipdef.h и т. Д. Я предполагаю, что моя DLL призывая элементы со статической библиотекой, которые конфликтуют с добавлением этого включения на этом уровне. Подобно порядку, в котором включены Windows.h и Winsock.h, возникают проблемы. Любые идеи, чтобы обойти это без необходимости воссоздать статическую библиотеку? –

+0

Попробуйте следующее: http://stackoverflow.com/questions/17789807/converting-managed-systemstring-to-stdstring-in-c-cli; который не требует этого заголовочного файла. – Matt

+0

Это похоже на меня. Позвольте мне перейти через некоторый код, прежде чем официально закрыть это. Еще раз спасибо за ваши ответы. –

Смежные вопросы