Jak stworzyć wrapper dla biblioteki DLL w C++/CLI

Odpowiedz Nowy wątek
2016-11-25 10:48
0

Witam,

Na wstępie przedłożę rys historyczny. Mam do podpięcia do aplikacji C# DLL w C++. DLLka owa eksportuje dokładnie jedną funkcję - GetCmsClientFactory. Funkcja ta zwraca obiekt (a raczej wskaźnik do niego), dzięki któremu mogę sobie utworzyć klienta i dalej sobie działać. Jako, że nie mogę użyć pinvoke, postanowiłem napisać wrapper w C++/CLI.

To co mam to plik dll oraz pliki nagłówkowe. Doczytałem, że aby sobie wygodnie pisać potrzebuję plik lib. Znalazłem sposób na wygenerowanie tego pliku:
https://adrianhenke.wordpress[...]/05/create-lib-file-from-dll/

W opisany pod tym linkiem sposób utworzyłem plik lib, ale wydaje się nie pomagać, bo jak już wspomniałem dll ekportuje tylko jedną funkcję. Ten plik dodałem do Linker/Input/AdditionalDependencies i upewniłem się, że ścieżka jest dobra.

Mimo wszystko spróbowałem jakoś to posklejać. Dodałem do "External Dependencies" pliki nagłówkowe, a w pliku nagłówkowym mojej testowej klasy dodałem include z plikiem nagłówkowym klasy ICmsClientFactory:

#pragma managed(push, off)
#include "SDKHeaders\ICmsClientFactory.h"
#pragma comment(lib, "cms_sdk.lib")
#pragma managed pop

W efekcie dostaję masę błędów. Niektóre odnoszą się do plików nagłówkowych które już w "External Dependencies" były w momencie gdy utworzyłem projekt.
Przykład:

    /**
      * Zarejestruj callback. Zwraca FALSE jeśli taki callback jest już 
      * zarejestrowany.
      */
    virtual BOOL Register( ICallbackEx *pCallback, 
            IUnknown *pData, 
            __int64 llData ) = 0;

Error C2275 'ICallbackEx': illegal use of this type as an expression

Inne błędy wskazują, że brak jest przeciążenia dla wirtualnych metod. Wiem, że nie muszę mieć pliku lib żeby zrobić LoadLibrary i GetProcAddress, ale jak potem korzystać z całego wachlarza obiektów?

Drugim problemem jest błąd:
Error C3280 'SDKClrWrapper::Wrapper::Init': a member-function of a managed type cannot be compiled as an unmanaged function SDK.ClrWrapper
To jest plik cpp, a w pliku nagłówkowym mamy owe #pragma managed.... Problem rozwiązuje zamiana #pragma managed pop na pragma managed(push, on), ale wydaje mi się, że to nie jest dobre rozwiązanie.

Walczę z tym już od chwili dłuższej drepcząc w miejscu, dlatego zwracam się o pomoc, żeby z tego miejsca ruszyć. W jaki sposób poprawnie zaimportować DLL?

Jestem programistą C# i programowałem w C++ dawno temu na studiach i moja wiedza na dzień dzisiejszy jest co najwyżej podstawowa. Dodam jeszcze, że nie jest moim celem zgłębianie wiedzy ani w zakresie C++ ani w zakresie CLI. Potrzebuję tylko dobrać się do tego z poziomu C#.

edytowany 1x, ostatnio: Sarrus, 2016-11-25 10:51

Pozostało 580 znaków

2016-11-27 23:13
0

DLLka owa eksportuje dokładnie jedną funkcję - GetCmsClientFactory.

Jak wygląda dokładnie nagłówek tej funkcji?

Co to jest za klasa ICmsClientFactory i jak wygląda?

Pozostało 580 znaków

2016-11-28 08:44
0

W przykładowym kodzie jest coś takiego:

typedef ICmsClientFactory *GET_CMS_CLIENT_FACTORY();

i wywołanie:

GET_CMS_CLIENT_FACTORY *GetCmsClientFactory = (GET_CMS_CLIENT_FACTORY *)::GetProcAddress( client.m_hClientDll, "GetCmsClientFactory" );

Zawartość pliku ICmsClientFactoryh:

#pragma once

#include"IAppLog.h"
#include"ICmsClient.h"
#include"ITaskScheduler.h"
#include"IFrameAllocator.h"

class ICmsClientFactory : public IUnknown
{
public:
    virtual BOOL Init( 
        ITaskScheduler *pScheduler = NULL,
        ITaskQueue *pThreadPool = NULL,
        IFrameAllocator *pAllocator = NULL,
        IAppLog *pLog = NULL ) = 0;

    virtual BOOL CreateClient( ICmsClient **pClient ) = 0;
    virtual void Exit() = 0;
    virtual IAppLog *Log() = 0;
    virtual ITaskQueue *ThreadPool() = 0;
    virtual ITaskScheduler *Scheduler() = 0;
    virtual IFrameAllocator *Allocator() = 0;
};

class __declspec( uuid("{B4041BE8-B1E6-485f-AD3D-BF79FDDFFD3B}") ) ICmsClientFactory;

Pozostało 580 znaków

2016-11-28 11:54

Szukałem czego mi brakuje i w końcu znalazłem. Brakowało mi jednej linijki w stdafx.h:

#include <Unknwn.h>

:|

Teraz projekt mi się kompiluje. Pozostaje jeszcze kwestia pragma managed, ale ruszyłem wreszcie z miejsca :)

EDIT:
Z tym sobie już poradzę. To wyczerpuje temat.

edytowany 1x, ostatnio: Sarrus, 2016-11-29 12:24

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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