jak zbudować dll'kę na podstawie .lib'a i pliku nagłówkowego

0

Witam,

Mam plik nagłówkowy i .lib'a i chciałbym z tego zrobić dll'a. Pracuję w Visual Studio 2005. Ważne jest aby stworzona biblioteka dll była niezależna od kompilatora, tj. żeby można ją było podlinkować zarówno w borlandzie jak i w visual'u.

Czy mógłby mi ktoś opisać w krokach co należy zrobić? A może jest jakiś dobry tutorial, który opisuje tą operację?

Pozdrawiam

0

masz plik .h i .lib, super! a gdzie kod? :)))

0
quetzalcoatl napisał(a)

masz plik .h i .lib, super! a gdzie kod? :)))

To może inaczej. Mam napisać swego rodzaju wrapper, który opakuje funkcje z .lib'a. Czyli muszę stworzyć dll, w której napiszę swoje funkcje, które wywołają funkcje z .lib'a. Nie mam źródła tego .lib'a, wiem tylko jakie ma funkcje (na podstawie .h).
Przepraszam, jeżeli mieszam, ale na co dzień zajmuję się raczej c# i totalnie nie wiem jak się do tego zabrać. Byłbym bardzo wdzięczny za pomoc.

0

No to co za problem? Rob tak samo, jakbys robil wlasnego dll-a, tylko zamiast kodu cpp dolacz lib-a. I wyeksportuj wszystkie funkcje, ktorych deklaracje sa w pliku .h.

0

a, to trzeba bylo od razu mowic ze ten lib to jest static library, myslalem ze to jest proxy do dllki..
jesli maja byc niezalezne od kompilatora, to musza one byc dostosowane nazewniczo do jezyka C, nie C++. kompilatory C++ maja rozny mangling i sie nie dogadaja.. ta w ogole, jaki jezyk? C? C++? zakladam ze C++..

powiedzmy ze w .lib i tym samym w .h masz funkcje:

extern "C"{
int raz();
void dwa(char* ble);
}

napisz sobie pliczek dllka.h:

extern "C" {
__declspec(dllexport) int moje_raz();
__declspec(dllexport) void moje_dwa(char* ble);
}

oraz pliczek dllka.cpp:

#include "tamten.h"
#include "dllka.h"

int moje_raz()
{   return raz();
}

void moje_dwa(char& ble)
{   dwa(ble);
}

teraz to skompiluj, zlinkuj wszystko lacznie z libem do .dll i juz.
uzywajac narzedzi z visual studio, to bedzie cos w stylu:

cl /c dllka.cpp
link /DLL dllka.obj tamten.lib /out:dllka.dll

oczywiscie tak trezba opakowac wszystkie funkcje z oryginalnego .lib..

0

Dzięki, dokładnie o to chodziło ;).

Jeszcze tylko takie malutkie pytanie. W pliku nagłówkowym jest klasa. W jaki sposób można "opakować" konstruktor oraz destruktor tej klasy? Może dla ułatwienia pokażę .h:

#ifndef ecgAnlsH
#define ecgAnlsH

class ecgAnRT;

typedef struct results
{
	unsigned long Index;
	unsigned char PeakType;
	unsigned char ArrhythmiaType;
	//----------------------
	short *ST1level;
	short *ST2level;
	short *ST1dev;
	short *ST2dev;
	//----------------------
	unsigned char ok;
	unsigned short HeartRate;
	unsigned char RhythmIrregularity;
	short *ADCoscLevel;
	short *NoiseLevel;

}results;


class ecgAnls
{
	public:
		//Konstruktor
		ecgAnls(float fs);
		ecgAnls(float fs, int nChnls);
		
		~ecgAnls(void);
		
		int processECGsamples(short *multiChannelECGblock, int nSamplesPerChannel, unsigned long smplPerChannelIndex,  results &resultsStruct);
		
		float ** getAverageECGperiod(long &ECGperiodLen, long &STLind, long &ST1ind, long &ST2ind);
		
		float ** getReferenceECGperiod(long &ECGperiodLen, long &STLind, long &ST1ind, long &ST2ind);
		//**************************************************************************************************************************************

		void insertSample(short sample, short sampleAux, unsigned long index);

		//Przetwarzanie
		unsigned long processData(void);
		
		float ** getST1results(unsigned long * tableLength);
		float ** getST2results(unsigned long * tableLength);

		float ** getST1devResults(unsigned long * tableLength);
		float ** getST2devResults(unsigned long * tableLength);

		float * getSTparametersLeadI(long *ECGperiodLen, long * STLind, long * ST1ind, long * ST2ind);
		float * getSTparametersLeadII(long *ECGperiodLen, long * STLind, long * ST1ind, long * ST2ind);

		float * getECGperiodRefLeadI(long *ECGperiodLen, long * STLind, long * ST1ind, long * ST2ind);
		float * getECGperiodRefLeadII(long *ECGperiodLen, long * STLind, long * ST1ind, long * ST2ind);
		void setBaseLinePoint2RpointDist(float milisecDist);
		void setJpoint2RpointDist(float milisecDist);
		void setSTpoint2JpointDist(float milisecDist);
		
		void setNperiods2average(int n);


		float getBaseLinePoint2RpointDist(void);
		float getJpoint2RpointDist(void);
		float getSTpoint2JpointDist(void);
		
		int getNperiods2average(void);
		//*********************************************************************************************
		
		long getBaseLinePoint2RpointDistInd(void);
		long getJpoint2RpointDistInd(void);
		long getSTpoint2JpointDistInd(void);

		float getST1devLeadImax(void);
		float getST1devLeadIImax(void);
		float getST1devLeadImin(void);
		float getST1devLeadIImin(void);
		float getST2devLeadImax(void);
		float getST2devLeadIImax(void);
		float getST2devLeadImin(void);
		float getST2devLeadIImin(void);
		
		unsigned long ** getResults(unsigned long * tableLength);

		void reset(void);

		float getECGlibVersion(void); 

		//=====================Interface=================================
		void setAmplitudeThreshold(float ampThLev);

		void setPathologicalWidth(float vWidth);

		void setPacerWidth(float vWidth);
		float getPacerWidth(void);

		void setPacer(int on_off);
		int getPacer(void);

		void setVTachycardiaBPMstart(float tahBPMstrt);
		float getVTachycardiaBPMstart(void);

		void setSVTachycardiaBPMstart(float SVtahBPMstrt);
		float getSVTachycardiaBPMstart(void);

		void setBradycardiaBPMstart(float BradBPMstrt);
		float getBradycardiaBPMstart(void);

		void setPrematureBeatRatio(float pbRatio);

		void setPauseDurationBounds(float minPauseDuration, float maxPauseDuration);
		void getPauseDurationBounds(float &minPauseDuration, float &maxPauseDuration);

		void setR2TmaxDist(float milisecDist);

		void setNbeats4HRmeasure(int nBeats);

		void setNbeats4rhythmIrregMeasure(int nBeats);

		void setACintrFreq(float intrFq);

		void setADClimits(float minLev, float maxLev, float minLevMiliVolt, float maxLevMiliVolt);
		
		void setPercentPrematurity(int percentValue);
		int getPercentPrematurity(void);

		void setMultiformSensitivity(int v1_to_10);
		int getMultiformSensitivity(void);

		//==============Auxiliary  methods for displaying===============
		int buffDuration2maxBufSize(float duration);

		void setDispBufSize(int size);

		unsigned long getDispIndex(int k);

		int getDispPeakEvent(int k);

		int getDispArtmEvent(int k);

		float getDispST1devLead1event(int k);
		float getDispST2devLead1event(int k);
		float getDispST1devLead2event(int k);
		float getDispST2devLead2event(int k);

		int getDispBufSize(void);

		void getDispPeakEventName(int k, char *pName);

		void getDispArtmEventName(int k, char *aName);

		/*<><>*/// ++++++ AUXILIARY INFORMATION INTERFACE METHODS ++++++++++++++++++++++++++++++++++++++++++
		/*<><>*///Getting rythm irregularity indicator (for current index)
		/*<><>*/float getDispRythmIrregularity(int k);

		/*<><>*///Getting ADC network oscillation amplitude (for current index)
		/*<><>*/float getDispADCnetworkAmp(int k);

		/*<><>*///Average heart rate (for current index)
		/*<><>*/float getDispAverageHeartRate(int k);

		/*<><>*///Getting ADC network oscillation amplitude for the second lead signal (for current index)
		/*<><>*/float getDispAuxADCnetworkAmp(int k);

		/*<><>*///Noise level (for current index)
		/*<><>*/float getDispNoiseLev(int k);

		/*<><>*///Noise level for 2 lead (for current index)
		/*<><>*/float getDispAuxNoiseLev(int k);
		/*<><>*/// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		//===============================================================

		int isArrhythmiaDataReady(void);
		int isSTDataReady(void);

	private:
		ecgAnRT *ecgAnReTm;
		
};
#endif

Tak to wygląda. Od razu zaznaczam, że kod nie jest mój, ja mam go tylko "opakować".

0

tak z ciekawosci spytam - a jak opakowales jej metody ktore potrzebuja instancji klasy?:)

odpowiadajac: na upartego:

void* utworz(){return new klasa();}
void zniszcz(void*ptr){delete (klasa*)ptr;}
cos wywolaj_metode_xxx(void*ptr, ble arg1, bum arg2){return ((klasa*)ptr)->xxx(ble,bum);}

ale to um, chamówa, ale jedyne wyjscie jak masz eksportowac do C..

a tak w ogole, to jesli masz wyeksportowac klase, to moim zdaniem szkoda Twojego zachodu!! NIE DA SIE "normalnie" wyeksportowac klasy tak zeby kazdy kompilator ja przyjal. poza powyzszym lopatologicznym rozwiazaniem, jedyne poprawne wyjscie, pozwalajace wyeksportowac klase jako klase, to przygotowac po jednym zestawie dllek na kazdy kompilator jaki ma byc uzyty pozniej. zakladajac takie podejscie, eksport klasy to banal:

tak w ogole, chyba skojarzylem jak to zrobic bez funkcji wrappujacych - ten plik "dll.cpp" powinien zalatwic wszystko. tylko go skompilowac i zlinkowac jak wyzej:

#include "tamtenlib.h"
#include "tamtaklasa.h"
int __declspec(dllexport) raz();
void __declspec(dllexport) dwa(char* ble);
class __declspec(dllexport) klasa;

ps: analizator elektrokardiogramow?

0
quetzalcoatl napisał(a)

tak z ciekawosci spytam - a jak opakowales jej metody ktore potrzebuja instancji klasy?:)

odpowiadajac: na upartego:

void* utworz(){return new klasa();}
void zniszcz(void*ptr){delete (klasa*)ptr;}
cos wywolaj_metode_xxx(void*ptr, ble arg1, bum arg2){return ((klasa*)ptr)->xxx(ble,bum);}

ale to um, chamówa, ale jedyne wyjscie jak masz eksportowac do C..

Dokładnie, to jest mój cel: eksport do C. Tylko ta klasa strasznie mi tu miesza.

quetzalcoatl napisał(a)

a tak w ogole, to jesli masz wyeksportowac klase, to moim zdaniem szkoda Twojego zachodu!! NIE DA SIE "normalnie" wyeksportowac klasy tak zeby kazdy kompilator ja przyjal. poza powyzszym lopatologicznym rozwiazaniem, jedyne poprawne wyjscie, pozwalajace wyeksportowac klase jako klase, to przygotowac po jednym zestawie dllek na kazdy kompilator jaki ma byc uzyty pozniej. zakladajac takie podejscie, eksport klasy to banal:

Właściwie to nie muszę eksportować klasy, raczej na wyjściu ma być zestaw funkcji, które ona oferuje.

quetzalcoatl napisał(a)

ps: analizator elektrokardiogramow?

bingo ;)

Dziękuję, i tak mi dużo wyjaśniłeś. Jeszcze jak byś mi tylko podpowiedział, jak można "pozbyć się" tej obiektowości, aby zejść do C...

0

no przeciez napisalem wyraznie, nie czytales?:)))

void* utworz(){return new klasa();}  //KONSTRUKTOR, zwraca "UCHWYT"
void zniszcz(void*ptr){delete (klasa*)ptr;}  //DESTRUTKTOR, zwalnia "UCHWYT"
cos wywolaj_metode_xxx(void*ptr, ble arg1, bum arg2){return ((klasa*)ptr)->xxx(ble,bum);}  //METODA, czyli odpal funkcje na uchwycie

porownaj ze starym dobrym C oraz fopen, fwrite, fclose.. FILE to byl nic innego jak "taki obiekt" dostosowany do C.. oczywiscie wszystkie w/w funkcje to musza wymienione w ich naglowku jako __declspec(dllexport) i wszystko musi byc objete extern "C" zeby byly exportowane bez manglingu

ps. oczywiscie, czego nie napisalem jeszcze, bedziesz potrzebowal drugi naglowek. ten z dllexport sluzy do kompilacji, a dla klienta ktory tej dllki bedzie uzywac potrzeba blizniaczego naglowna z dllimport wszedzie. zwykle to sie zalatwia to odpowiednimi #define, ale to Ci nie bedzie potrzebne, bo to maly projekt

0
quetzalcoatl napisał(a)

no przeciez napisalem wyraznie, nie czytales?:)))

void* utworz(){return new klasa();}  //KONSTRUKTOR, zwraca "UCHWYT"
void zniszcz(void*ptr){delete (klasa*)ptr;}  //DESTRUTKTOR, zwalnia "UCHWYT"
cos wywolaj_metode_xxx(void*ptr, ble arg1, bum arg2){return ((klasa*)ptr)->xxx(ble,bum);}  //METODA, czyli odpal funkcje na uchwycie

A więc trzeba zastosować metodę "chamską" :)

quetzalcoatl napisał(a)

porownaj ze starym dobrym C oraz fopen, fwrite, fclose.. FILE to byl nic innego jak "taki obiekt" dostosowany do C.. oczywiscie wszystkie w/w funkcje to musza wymienione w ich naglowku jako __declspec(dllexport) i wszystko musi byc objete extern "C" zeby byly exportowane bez manglingu

ps. oczywiscie, czego nie napisalem jeszcze, bedziesz potrzebowal drugi naglowek. ten z dllexport sluzy do kompilacji, a dla klienta ktory tej dllki bedzie uzywac potrzeba blizniaczego naglowna z dllimport wszedzie. zwykle to sie zalatwia to odpowiednimi #define, ale to Ci nie bedzie potrzebne, bo to maly projekt

</quote>

Mam nadzieję, że dam radę ;)

Quetzalcoatl, wielkie wielkie dzięki. Nawet nie wiesz jak bardzo mi pomogłeś. C/C++ to dla mnie "obcy teren", na co dzień zajmuję się c#. Ale teraz widzę światełko w tunelu :-).

Jeszcze raz dziękuję i pozdrawiam

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