Używanie bibliotek c++ w C#

Używanie bibliotek c++ w C#
Mikolaj Pydzik
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 39
0

Cześć,
jak stworzyć bibliotekę c++ tak aby działała w programach c#, tak aby nie trzeba było doinstalowywać żadnych innych bibliotek.
Z góry dziękuję.

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
0

Piszesz wrapper używając C++ CLI gdzie możesz mieszać .net ze zwykłym C++, C# już będzie widział to co napiszesz w C++ CLI.

Mikolaj Pydzik
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 39
0
MarekR22 napisał(a):

Piszesz wrapper używając C++ CLI gdzie możesz mieszać .net ze zwykłym C++, C# już będzie widział to co napiszesz w C++ CLI.

Po prostu jak napisać bibliotekę c++ i jak ją zaimportować w C#

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
0

C++

Kopiuj
class MojaDziwnaKlasa
{
public:
       ~MojaDziwnaKlasa();
       MojaDziwnaKlasa();

       void ZrobCos(const std::string &s);
};

C++ CLI header

Kopiuj
#pragma once

#include "cpp/MojaDziwnaKlasa.h"

using namespace System;
using namespace System::Collections::Generic;
using namespace System::Collections::ObjectModel;

namespace Pydzik {
	namespace Biblioteka {
             public ref class MojaDziwnaKlasa
             {
             public:
                    !MojaDziwnaKlasa();
                    MojaDziwnaKlasa();

                    void ZrobCos(String^ s);
             internal:
             private:
                    unmanaged_ptr<MojaDziwnaKlasa> m_pDziwnaKlasa;
             };

C++ CLI header

Kopiuj
#pragma once

#include "cpp/MojaDziwnaKlasa.h"
#include "cli/Utils.h"

using namespace System;
using namespace System::Collections::Generic;
using namespace System::Collections::ObjectModel;

using namespace Biblioteka

Biblioteka::MojaDziwnaKlasa::!MojaDziwnaKlasa()
{}

Biblioteka::MojaDziwnaKlasa::MojaDziwnaKlasa()
    : m_pDziwnaKlasa(new MojaDziwnaKlasa)
{}

void Biblioteka::MojaDziwnaKlasa::ZrobCos(String^ s)
{
     m_pDziwnaKlasa->ZrobCos(StringToSTLString(s));
}

Gdzieś w utils:

Kopiuj
std::string StringToSTLString(String^ s)
{
	if (System::String::IsNullOrEmpty(s))
	{
		return "";
	}

	array<Byte>^ encodedBytes = System::Text::Encoding::UTF8->GetBytes(s);
	std::string result;
	result.reserve(static_cast<size_t>(encodedBytes->Length));
	for (int32_t i = 0; i < encodedBytes->Length; ++i)
	{
		result += encodedBytes[i];
	}
	return result;
}
Mikolaj Pydzik
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 39
0

A jak zaimportować do aplikacji C#?

abrakadaber
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 6610
0

gościu bana na google masz?

Azarien
  • Rejestracja: dni
  • Ostatnio: dni
1
MarekR22 napisał(a):
Kopiuj
std::string StringToSTLString(String^ s)

Ło ja cie. A po co skoro to już jest.

Kopiuj
#include <string>
#include <msclr/marshal_cppstd.h>

int main()
{
	System::String ^s1 = L"Ala ma kota";
	std::string s2 = msclr::interop::marshal_as<std::string>(s1);
}

Tak samo w drugą stronę.
Poza tym lepiej używać wstring, przynajmniej konwersja będzie bezstratna.

JU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5046
0

Nie trzeba wcale posługiwać się CLI. CLI jest konieczne, jeśli chcesz korzystać w C++ z dllki pisanej w C#. Tutaj zależy od tego, co tak naprawdę potrzebujesz. Bo jeśli chcesz eksportować wiele klas, to wtedy CLI. Ale jeśli potrzebujesz eksportować zwykłe funkcje, to CLI Ci zupełnie nie jest potrzebne. Po prostu musisz taką dllkę odpowiednio napisać. Czyli np. nie używasz std::string, tylko char *. Itd.

Możesz też w taki sposób wyeksportować cały obiekt. Musiałbyś napisać funkcję w stylu (w C++) createMyObj(), która zwraca w jakiś sposób wskaźnik do utworzonego obiektu, a potem musiałbyś eksportować funkcje, które przyjmują w parametrze ten wskaźnik. Coś w stylu:

Kopiuj
class MyClass
{
public:
  void Foo(const int & a);
  void Bar(const int & a, const std::wstring & str);
}

//te poniższe są eksportowane - pomijam declspec i konwencje wywołania:

bool createMyClassObj(MyClass &* ptr)
{
  try
  {
    ptr = new MyClass();
    return true;
  }catch(...) { /* co tam potrzebujesz */ }
}

void destroyMyClassObj(MyClass * pObj)
{
  delete pObj;
}

void foo(MyClass * pObj, const int & a)
{
  pObj->Foo(a);
}

void bar(MyClass * pObj, const int & a, const wchar_t * str)
{
  pObj->Bar(a, str);
}

Także w ogóle nie musisz mieć warstwy CLI. Zależy tylko co tak naprawdę potrzebujesz osiągnąć. Jakie masz wymagania, co będziesz eksportował. Bo pewne rzeczy będą ułatwione z użyciem CLI (pomimo, że musisz napisać dodatkową warstwę), ale pewne bez tego.

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
0

FYI jeśli mówimy o używaniu tylko prostych funkcji to jest coś takiego jak DllImportAttribute.
https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx
Dzięki temu prosto można używać winapi (ale to jest API C).
Z tego co mi wiadomo w przypadku klas trzeba pisać wrapper C++ CLI jak opisałem wyżej.
Mogę się mylić bo .net to nie jest moja działka.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.