Używanie bibliotek c++ w C#

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ę.

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.

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#

0

C++

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

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

C++ CLI header

#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

#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:

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;
}
0

A jak zaimportować do aplikacji C#?

0

gościu bana na google masz?

1
MarekR22 napisał(a):
std::string StringToSTLString(String^ s)

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

#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.

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:

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.

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.

1 użytkowników online, w tym zalogowanych: 0, gości: 1