Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[c++] Wywoływanie funkcji z dll

29 Gru 2010 16:17 1808 8
  • Poziom 9  
    Witam!

    Piszę aplikację w c++, która ma korzystać z biblioteki dll napisanej w delphi. Do biblioteki nie ma dołączonego żadnego innego pliku z deklaracjami funkcji, tylko sama dll-ka. Z dokumentacji biblioteki wynika, że funkcja którą chcę wywoływać ma następującą postać:

    Code:
    function  Command(LnId : TLnId; InpStr: string; var OutBufPtr :pchar; var ErrBufPtr : pchar):TStatus; stdcall;


    przy czym TLnId oraz TStatus to podobno są integery.

    Problem polega na tym że w momencie wywołania tej funkcji w c++ aplikacja się wysypuje. Jak powinna wyglądać poprawna deklaracja tej funkcji w c++ oraz jak poprawnie dołączyć tę bibliotekę do aplikacji??

    W tej chwili fragment pliku nagłówkowego z deklaracją ma następującą postać:

    Code:
    #ifdef DLL_BUILD
    
    #define DLL_OPT __declspec(dllexport)
    #else
    #define DLL_OPT __declspec(dllimport)
    #endif

    #ifdef __cplusplus
    extern "C" {
    #endif

    int DLL_OPT Command(int LnId, char * InpStr, char ** OutBufPtr, char ** ErrBufPtr);

    #ifdef __cplusplus
    }
    #endif
  • Pomocny post
    Poziom 42  
    Nie sądzę, aby były to typy integer, lecz całe obiekty, a to co znajduje się w wywołaniu jest tylko wskaźnikiem. Niemniej, jeśli znajdują się tam typy String (w obiekcie), to dal DLL nie nadaje się do uruchomienia z programami pisanymi na innych platformach. Tak samo String - nie wolno takiego typu stosować przy pisaniu DLL w Delphi bez korzystania ze specyficznego modułu. Ergo - nie przejdzie z innymi językami programowania.
    Wniosek - autor DLL może ją sobie ***.
  • Poziom 9  
    Dzięki za szybką odpowiedź.

    Wcześniej były podejmowanie próby uruchomienia dll-ki w C#, sama funkcja command (nota bene jedyna udostępniania przez bibliotekę) byłą wywoływana lecz pojawiał się inny problem w dalszej pracy z dll-ka. Jednak na podstawie sposobu podpięcia funkcji command w c# można wnioskować, że rzeczywiście typy TLnId i TStatus to są integery natomiast string można by zastąpić czymś na kształt C-Stringa. Poniżej deklaracja z C#:

    Code:
    private static extern int CommandBase(int LnId, [MarshalAs(UnmanagedType.LPArray)] byte[] InpStr, ref System.IntPtr OutBufPtr, ref System.IntPtr ErrBufPtr);


    Pytanie jak .NET poradził sobie z tym stringiem i co dalej w c++??
  • Poziom 9  
    Od zawsze są problemy z tą biblioteką... achhh
    Ok, takim wypadku dzięki i pozdrawiam.
  • Poziom 17  
    Jakieś komunikaty aplikacja wyświetla konkretne podczas wywalenia się? W jakim środowisku budujesz swoją aplikację? Coś debugger wyrzuca? Spróbować można to uruchomić, nie ma co się poddawać na początku :)
  • Poziom 9  
    Witam!
    kompilator:g++, debugger: gdb. U mnie funkcja funkcja zwraca 2 razy kod 102 z tego co pamiętam (ale pewien nie jestem) oznacza to że nie rozumie komendy przekazywanej przez tego stringa, natomiast zawsze przy trzecim wywołaniu występuje SIGSEGV. U kolegi z zespołu natomiast przy pierwszym wywołaniu zatrzymuje się w bliżej nie określonym miejscu w bibliotece i stoi w funkcji Raise Exception. Środowiska mamy te same, różnica taka że on to uruchamia pod windows xp a ja 7.
  • Poziom 9  
    Ok, dll-ka została przerobiona - typ string został zamieniony na pchar i w sumie problem zniknął tzn. funkcja rozumie komendy wysyłane w omawianym parametrze. Jednak pojawił się następny problem. Biblioteka do poprawnego działania potrzebuje aby użytkownik zdefiniował funkcję alokującą pamięć i przesłał jej adres, taki callback. Gdy w pewnym wywołaniu funkcji biblioteka zechce zwrócić jakieś dane to wywołuje sobie tę funkcję i alokuje pamięć przypisując wskaźnik zmiennym użytkownika. Więc wychodzi na to że biblioteka wie gdzie jest funkcja alokująca, wywołuje ją lecz bierze sobie zupełnie inny adres niż ten zaalokowany, właściwie to w tej funkcji mogą być jakieś bzdety i tak biblioteka przypisze zmiennej jakiś swój adres.
    Funkcja alokująca:
    Code:

    char * DllMalloc(int size)
    {
       try
       {
          return new char[size];
       }
       catch(std::bad_alloc)
       {
          /* @todo du samsin */
          return NULL;
       }
    }


    Wywołanie:
    Code:

    char * oB = NULL;
    char * eB = NULL;
    char  com[] = {"GET_DEV_DEF"};
    unsigned int ret = CommandCC(-1, com, &oB, &eB);


    Koniec końców oB i eB zawsze pokazują na adresy nie związane z adresami uzyskiwanymi w funkcji DllMalloc. Jakieś pomysły?
  • Poziom 9  
    Ok już wszystko działa, przy deklaracji funkcji brakowało:
    Code:
     __attribute__((stdcall))
    Dzięki za pomoc i pozdrawiam.