Jak przesłać dynamicznie utworzony objekt do dll?

problemy z funkcjonowaniem bibliotek, komponentów itp.

Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez duf » poniedziaÅ‚ek, 24 maja 2010, 10:28

Próbuje przesłać obiekt do dll ale podczas próby wczytania pliku dostaję access violation:
Kod: Zaznacz cały
TImage* newimage = new TImage(this);
typedef void(* __stdcall pDruk)( TImage* );
...........................................................
Druk ( newimage );

DLL
Kod: Zaznacz cały
extern "C" void __declspec (dllexport) __stdcall Druk( TImage* newimage )
{
  newimage->Picture->LoadFromFile( "picture.bmp" );
}

Czy na pewno obiekty przekazuję się do dll przez wskaźnik?
Avatar użytkownika
duf
Intelektryk
Intelektryk
 
Posty: 175
Dołączył(a): czwartek, 9 października 2008, 13:02
PodziÄ™kowaÅ‚ : 17
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows 10
Kompilator: XE8
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez Cyfrowy Baron » poniedziaÅ‚ek, 24 maja 2010, 10:37

A dlaczego ta funkcja jest typu __stdcall i co tam robi ten typedef czym to uzasadniasz?

Przecież można to zrobić tak:

w aplikacji:
Kod: Zaznacz cały
TImage* newimage = new TImage(this);
extern  "C" __declspec(dllimport) void Drug(TImage *newimage);


w dll:
Kod: Zaznacz cały
extern  "C" __declspec(dllexport) void Drug(TImage *newimage);

void Drug(TImage *newimage)
{
  newimage->Picture->LoadFromFile( "picture.bmp" );
}
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez duf » poniedziaÅ‚ek, 24 maja 2010, 10:39

Cyfrowy Baron napisał(a):A dlaczego ta funkcja jest typu __stdcall i co tam robi ten typedef czym to uzasadniasz?

Wtedy w funkcji GetProcAddress(MYDLL, "Druk") nie muszę wpisywać znaczka "_" czyli GetProcAddress(MYDLL, "_Druk")
Avatar użytkownika
duf
Intelektryk
Intelektryk
 
Posty: 175
Dołączył(a): czwartek, 9 października 2008, 13:02
PodziÄ™kowaÅ‚ : 17
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows 10
Kompilator: XE8
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez Cyfrowy Baron » poniedziaÅ‚ek, 24 maja 2010, 10:52

Funkcje typu __stdcall inaczej się stosuje i dlatego masz błąd. Jeżeli jedynym uzasadnieniem jest nieużywanie podkreślnika "_" to ja nie wiem do czego Ty zmierzasz. Co za różnica, czy go użyjesz czy nie?!
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez duf » poniedziaÅ‚ek, 24 maja 2010, 12:18

CoÅ› jest nie tak bo otrzymujÄ™ ciÄ…gle access violation in module Projectmydll.dll
aplikacja:
Kod: Zaznacz cały
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
extern  "C" __declspec(dllimport) void Druk( TImage*);

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  TImage* newimage = new TImage(this);
 
  HINSTANCE MYDLL;

   typedef void(* pDruk )( TImage* );
   pDruk Druk;

  if ( (MYDLL = LoadLibrary(L"Projectmydll.dll")) == NULL ) { ShowMessage( "DLL nie znaleziono." ); return; }
  if ( (Druk = (pDruk)GetProcAddress(MYDLL, "_Druk")) == NULL ) { ShowMessage( "Funkcji nie odnaleziono." ); return; }

  Druk ( newimage );

  FreeLibrary(MYDLL);

  delete newimage;
}
//---------------------------------------------------------------------------


DLL
Kod: Zaznacz cały
extern "C" __declspec (dllexport) void Druk ( TImage* newimage );

void Druk ( TImage* newimage )
{
  try
  {
     newimage->Width = 100;   
     newimage->Picture->LoadFromFile( "plik.bmp" );
  }
  catch( Exception& e ) { ShowMessage(e.ToString()); }
}

Problem jest w ładowaniu pliku .bmp. W Button1Click nie ma z tym problemu. Zrobiłem już całkiem nowy projekt tylko dla tego celu. Gdy usunę wpis z ładowaniem pliku nie dostaje komunikatu o błędzie.
Avatar użytkownika
duf
Intelektryk
Intelektryk
 
Posty: 175
Dołączył(a): czwartek, 9 października 2008, 13:02
PodziÄ™kowaÅ‚ : 17
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows 10
Kompilator: XE8
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez Cyfrowy Baron » poniedziaÅ‚ek, 24 maja 2010, 12:21

Powinno być:
Kod: Zaznacz cały
extern  "C" __declspec(dllimport) void Druk( TImage* newimage);


W bibliotece DLL dołącz w sekcji include plik:

Kod: Zaznacz cały
#include <Graphics.hpp>
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez duf » poniedziaÅ‚ek, 24 maja 2010, 13:16

To niczego nie zmieniło.
Avatar użytkownika
duf
Intelektryk
Intelektryk
 
Posty: 175
Dołączył(a): czwartek, 9 października 2008, 13:02
PodziÄ™kowaÅ‚ : 17
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows 10
Kompilator: XE8
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez Cyfrowy Baron » poniedziaÅ‚ek, 24 maja 2010, 13:51

Może dokończ, chociaż wątpie by to na coś wpłynęło:

Kod: Zaznacz cały
  TImage* newimage = new TImage(this);
  Newimage->Parent = this;


A to jest źle:
Kod: Zaznacz cały
  catch( Exception& e ) { ShowMessage(e.ToString()); }



Returns a string containing the class name.

By default, the System.TObject.ToString returns a string containing the class name of the instance that is being called.

For example, calling System.TObject.ToString on a TButton instance returns a string containing "TButton".



Powinno być:
Kod: Zaznacz cały
  catch( Exception& e ) { ShowMessage(e.Message); }



A komunikatami błędów to wogóle lepiej tak zarządzać:
Kod: Zaznacz cały
void ErrorExit(String lpFun)
{
   LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;

    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
      (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen(lpFun.t_str())+40)*sizeof(TCHAR));
    wsprintf((LPTSTR)lpDisplayBuf,
        TEXT("%s failed with error %d: %s"),
      lpFun, dw, lpMsgBuf);
   MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
   ExitProcess(dw);
}
//---------------------------------------------------------------------------
void Druk ( TImage* newimage )
{
  try
  {
     newimage->Width = 100;   
     newimage->Picture->LoadFromFile( "plik.bmp" );
  }
  catch(...)
  {
   ErrorExit("WÅ‚asna teść, reszta zostanie dodana");
  }
}





A tak wogóle, to źle podłączasz tą bibliotekę dynamicznie. Poczytaj w serwisie Cyfrowy Baron dział: teoria -> Tworzenie DLL -> Dynamiczne podłączanie biblioteki DLL
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez duf » poniedziaÅ‚ek, 24 maja 2010, 14:08

Error 87. Parametr jest niepoprawny.
Avatar użytkownika
duf
Intelektryk
Intelektryk
 
Posty: 175
Dołączył(a): czwartek, 9 października 2008, 13:02
PodziÄ™kowaÅ‚ : 17
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows 10
Kompilator: XE8
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez Cyfrowy Baron » poniedziaÅ‚ek, 24 maja 2010, 15:04

Źle podÅ‚Ä…czasz tÄ… bibliotekÄ™ dynamicznie. ► patrz serwis: Cyfrowy Baron dziaÅ‚: teoria -> Tworzenie DLL -> Dynamiczne podÅ‚Ä…czanie biblioteki DLL.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
PodziÄ™kowaÅ‚ : 12
OtrzymaÅ‚ podziÄ™kowaÅ„: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez banita » poniedziaÅ‚ek, 24 maja 2010, 16:57

z tego co sie zorientowalem to masz w swojej aplikacji obiekt TImage i chcesz go przekazac do dll.

na temat dll:

Kod: Zaznacz cały
#if defined(__cplusplus)
extern "C"
{
#endif
__declspec(dllexport) void __stdcall openForm(TImage*);
#if defined(__cplusplus)
}
#endif

#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
   return 1;
}
//---------------------------------------------------------------------------

void __stdcall openForm(TImage* img)
{
   Tui_form* frm = new Tui_form(0); // sam po sobie sprzata
   frm->setImage(img);
   frm->ShowModal();
}

header
Kod: Zaznacz cały

#ifndef __DLL_TEST_
#define __DLL_TEST_

#if defined(__cplusplus)
extern "C"
{
#endif
__declspec(dllimport) void __stdcall openForm(TImage*);;
#if defined(__cplusplus)
}
#endif

#endif // __DLL_TEST_

ten dll ma w sobie forme 'Tui_form' na ktorej jest obiekt TImage. z poziomu napszej aplikacji przekazujemy wsk do obiektu TImage i w dll manipulujemy nim. to jest ten sam adres w pamieci wiec jesli w dll zaladujemy jakies obrazek to ten obrazek pokaze sie nam w TImage w aplikacji.

ladowanie dynamiczne:
Kod: Zaznacz cały
   HINSTANCE dllHandle;

   typedef void (*foo)(TImage*);
   foo foo_bar;
   dllHandle = LoadLibrary("d:\\TEST___\\dll_rs2010\\dll\\Debug\\dll_project.dll");
   foo_bar = reinterpret_cast<foo>(GetProcAddress(dllHandle, "openForm"));
   foo_bar(ui_image);

   FreeLibrary(dllHandle);

oczywiscie HINSTANCE dllHandle; czy typedef powinny znalesc sie gdzie indziej ale to tylko przyklad ....


ten kod zadziala prawidlowo.... do czasu.

FreeLibrary(dllHandle); <------ ta linijka powoduje usuniecie TImage z dll do ktorego odwolujemy sie w najszej aplikacji.
Avatar użytkownika
banita
Kreacjusz
Kreacjusz
 
Posty: 283
Dołączył(a): poniedziałek, 28 lipca 2008, 20:07
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 18
System operacyjny: Windows 7 Professional
Kompilator: C++Builder 2010 Update 5,
Delphi 2010 Update 5,
NetBeans 6.9(MinGw + Qt),
Visual Studio 2008 + Qt
Gadu Gadu: 0
    Windows 7Opera

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez duf » poniedziaÅ‚ek, 24 maja 2010, 18:00

banita napisał(a):oczywiscie HINSTANCE dllHandle;

Bo tylko ten typ mogę skompilować. Przy HANDLE wywala błąd:
aDruk Druk = (aDruk)GetProcAddress(DLLHandle, "_Druk"); <--- błąd
Cannot convert 'void *' to 'HINSTANCE__ *'
Type mismatch in parameter 'hModule' (wanted 'HINSTANCE__ *', got 'void *')

banita napisał(a):ten kod zadziala prawidlowo.... do czasu.
FreeLibrary(dllHandle); <------ ta linijka powoduje usuniecie TImage z dll do ktorego odwolujemy sie w najszej aplikacji.

Jaka rada?

Nie mogę zrobić takiego zapisu w dll typu:
Kod: Zaznacz cały
TForm* frm = new TForm(0);


[BCC32 Error] File1.cpp(66): E2015 Ambiguity between '_fastcall Forms::TForm::TForm(Classes::TComponent *) at e:\program files\borland\embarcadero\rad studio\7.0\include\vcl\Forms.hpp:1062' and '_fastcall Forms::TForm::TForm(HWND__ *) at e:\program files\borland\embarcadero\rad studio\7.0\include\vcl\Forms.hpp:1067'
Full parser context
File1.cpp(60): parsing: void Druk(Extctrls::TImage *)

Ostatnio edytowano poniedziałek, 24 maja 2010, 18:06 przez duf, łącznie edytowano 1 raz
Avatar użytkownika
duf
Intelektryk
Intelektryk
 
Posty: 175
Dołączył(a): czwartek, 9 października 2008, 13:02
PodziÄ™kowaÅ‚ : 17
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows 10
Kompilator: XE8
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez duf » poniedziaÅ‚ek, 24 maja 2010, 18:03

Cyfrowy Baron napisaÅ‚(a):Źle podÅ‚Ä…czasz tÄ… bibliotekÄ™ dynamicznie. ► patrz serwis: Cyfrowy Baron dziaÅ‚: teoria -> Tworzenie DLL -> Dynamiczne podÅ‚Ä…czanie biblioteki DLL.

Nawet jak przepisałem kod według tego opisu to i tak nie mogę go wykonać:
Kod: Zaznacz cały
TImage* newimage = new TImage(this);

  //HINSTANCE DLLHandle = LoadLibrary(L"Projectmydll.dll");
  HANDLE DLLHandle = LoadLibrary(L"Projectmydll.dll");
   if(DLLHandle != NULL)
   {
      typedef (*aDruk)(TImage*);

      aDruk Druk = (aDruk)GetProcAddress(DLLHandle, "_Druk");

      if( Druk != NULL) Druk( newimage );
   }
   else ShowMessage("Nie znaleziono wymaganej biblioteki dll.");

   FreeLibrary(DLLHandle);

  delete newimage;

ACCESS VIOLATION IN MODULE PROJECTMYDLL.DLL
Avatar użytkownika
duf
Intelektryk
Intelektryk
 
Posty: 175
Dołączył(a): czwartek, 9 października 2008, 13:02
PodziÄ™kowaÅ‚ : 17
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows 10
Kompilator: XE8
Gadu Gadu: 0
    Windows XPFirefox

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez banita » poniedziaÅ‚ek, 24 maja 2010, 20:10

zbuduj dll i aplikacje na bazie kodu ktory podalem i zobacz co sie dzieje
Avatar użytkownika
banita
Kreacjusz
Kreacjusz
 
Posty: 283
Dołączył(a): poniedziałek, 28 lipca 2008, 20:07
PodziÄ™kowaÅ‚ : 1
OtrzymaÅ‚ podziÄ™kowaÅ„: 18
System operacyjny: Windows 7 Professional
Kompilator: C++Builder 2010 Update 5,
Delphi 2010 Update 5,
NetBeans 6.9(MinGw + Qt),
Visual Studio 2008 + Qt
Gadu Gadu: 0
    Windows 7Opera

Re: Jak przesłać dynamicznie utworzony objekt do dll?

Nowy postprzez duf » wtorek, 25 maja 2010, 07:55

banita napisał(a):zbuduj dll i aplikacje na bazie kodu ktory podalem i zobacz co sie dzieje

[BCC32 Error] File1.cpp(66): E2451 Undefined symbol 'Tui_form'
Avatar użytkownika
duf
Intelektryk
Intelektryk
 
Posty: 175
Dołączył(a): czwartek, 9 października 2008, 13:02
PodziÄ™kowaÅ‚ : 17
OtrzymaÅ‚ podziÄ™kowaÅ„: 2
System operacyjny: Windows 10
Kompilator: XE8
Gadu Gadu: 0
    Windows XPFirefox

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Biblioteki i komponenty

Kto przeglÄ…da forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 16 gości

cron