Używanie bibliotek c++ w C#

Odpowiedz Nowy wątek
2017-06-29 12:07

Rejestracja: 3 lata temu

Ostatnio: 1 miesiąc temu

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

Pozostało 580 znaków

2017-06-29 13:03

Rejestracja: 12 lat temu

Ostatnio: 3 godziny temu

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.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
Można trochę jaśniej? - Mikolaj Pydzik 2017-06-29 13:07
jak pytanie będzie jaśniejsze to czemu nie. Przy tak ogólnikowym pytaniu dostajesz ogólnikową odpowiedź. - MarekR22 2017-06-29 13:10
Chcę dać metody C++ tak aby mogły być wykonywane w programach napisanych w C#, najlepiej wolał bym dać do biblioteki, ale może być też inna metoda. - Mikolaj Pydzik 2017-06-29 13:14
a czym to się różni od pierwotnego pytania? Skonkretyzowałeś cokolwiek? NIE! - MarekR22 2017-06-29 13:15
W TEMACIE ODPOWIADAMY POSTAMI A NIE KOMENTARZAMI! - abrakadaber 2017-06-29 13:23

Pozostało 580 znaków

2017-06-29 13:51

Rejestracja: 3 lata temu

Ostatnio: 1 miesiąc temu

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#

Pozostało 580 znaków

2017-06-29 13:59

Rejestracja: 12 lat temu

Ostatnio: 3 godziny temu

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

Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22, 2017-06-29 14:02

Pozostało 580 znaków

2017-06-29 15:07

Rejestracja: 3 lata temu

Ostatnio: 1 miesiąc temu

0

A jak zaimportować do aplikacji C#?

no właśnie ci to pokazałem. Jak masz już wrapper C++ CLI, to potem w C# robisz tyko import Pydzik.Biblioteka.MojaDziwnaKlasa i gotowe. - MarekR22 2017-06-29 22:24

Pozostało 580 znaków

2017-06-29 18:45

Rejestracja: 7 lat temu

Ostatnio: 7 godzin temu

0

gościu bana na google masz?


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

2017-06-29 19:46

Rejestracja: 16 lat temu

Ostatnio: 4 godziny temu

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.

edytowany 2x, ostatnio: Azarien, 2017-06-29 19:51
nie moja działka, skopiowałem od kogoś, od razu widziałem, że do d..y, ale nie chciało mi się szukać lepszego rozwiązania. - MarekR22 2017-06-29 22:14
swoją drogą jakiego kodowania używa msclr::interop::marshal_as? Nie widzę nic na ten temat w dokumentacji. Jeśli używa systemowego locale to jest nie do przyjęcia. - MarekR22 2017-06-29 22:19
Oczywiście że używa kodowania systemowego, byłoby dziwne gdyby używało innego. Dlatego zaleciłem std::wstring, które jest w UTF-16 podobnie jak System:String. Kodowanie UTF-8 pod Windows nie jest standardowe, jak go bardzo potrzebujesz to musisz sobie wyczarować. - Azarien 2017-06-30 00:43
skopiowałem to z biblioteki, która obsługuje wiele platform i wewnętrzna logika zakłada kodowanie utf-8, stąd ten kwiatek StringToSTLString. - MarekR22 2017-06-30 13:49

Pozostało 580 znaków

2017-06-30 09:51

Rejestracja: 17 lat temu

Ostatnio: 1 dzień temu

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.

no i jakim cudem używa się tego w C#? Gdzie masz przeskok do managed code? - MarekR22 2017-06-30 13:51
C# importuje sobie takie funkcje bez problemu. - Juhas 2017-06-30 15:31

Pozostało 580 znaków

2017-06-30 13:57

Rejestracja: 12 lat temu

Ostatnio: 3 godziny temu

0

FYI jeśli mówimy o używaniu tylko prostych funkcji to jest coś takiego jak DllImportAttribute.
https://msdn.microsoft.com/en[...]vices.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.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22, 2017-06-30 13:57
Nie, możesz zrobić taki myk, jak napisałem wyżej. Ale żeby posługiwać się faktycznie klasami, czyli masz klasę w C++ i tą samą klasę w C#, to wtedy musisz mieć CLI. Ale takie działanie jest głupie, bo musisz mieć tą samą klasę w 2 miejscach. Zmienisz coś w jednej (w publicznym interfejsie), musisz zmienić wszędzie. - Juhas 2017-06-30 15:33
jeśli klasa jest napisana w całości w C++/CLI (czyli nie jest wrapperem na klasę natywną) to wtedy nie trzeba zmieniać dwa razy. - Azarien 2017-06-30 20:04

Pozostało 580 znaków

Odpowiedz

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