Seite 1 von 2

C-Wrapper für PureBasic

Verfasst: 30.04.2010 18:26
von Mok
Hallo.

Ähnlich wie in diesem Topic möchte auch ich einen Wrapper für PureBasic machen, nur eben nicht von C++ für PB, sondern von C.
Also ok, einfach DLL bauen und dann in PB aufrufen, nur die Sache hat einen Haken: Das Programm sollte Plattformübergreifend funktionieren => DLLs sind nur Windows. Desweiteren wurde gzip auch auf einer Unix-Plattform geschrieben, daher könnte es Konflikte mit Win geben.

Ich habe auch den 7Zip Programmcode, wo auch die En-/Decoder-Libs enthalten sind, nur sind die in C++ geschrieben und (daher?) noch viel unübersichtlicher. Was zum Teufel heißt HRESULT, RINOK, g_MarkerInitializer und wie soll ich die Header portieren?

Gibt es irgendein Etwas, was sich wie eine Lib verhält, aber in Win und Linux-Systemen gleichermaßen läuft? Für Tipps, Tricks und Tutorials wäre ich auch sehr dankbar.

MfG, Mok

Re: C-Wrapper für PureBasic

Verfasst: 30.04.2010 19:20
von NicTheQuick
Mok hat geschrieben:Was zum Teufel heißt HRESULT, RINOK, g_MarkerInitializer und wie soll ich die Header portieren?
HRESULT ist nur ein Makro/Platzhalter für LONG.
Für RINOK hab ich folgendes gefunden:

Code: Alles auswählen

#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
Also auch wieder ein Makro.

Manchmal reicht googeln, manchmal musst du aber auch einfach nur in die Header schauen, die du included hast. Mit eclipse geht es noch einfacher. Dort drückst du STRG und klickst auf das Wort und er springt in den Header, wo es definiert wurde.

Im Übrigen gibt es für Linux ebenfalls Libraries. Meistens haben die die Endung ".so". Der C++-Quellcode kann ja plattformübergreifend geschrieben werden, aber kompilieren musst du die Libraries dann als DLL und als SO für jeweils 64 und 32 Bit.

Re: C-Wrapper für PureBasic

Verfasst: 30.04.2010 20:13
von Mok
@Nic: Danke, sehr hilfreicher Beitrag! :D
Heißt das, mir könnte das ganz egal sein, was das ganze Zeugs ist, weil ich es eh wahlweise als *.DLL/*.SO exportieren kann? Jetzt noch eine Interessensfrage: was sind das für komische Dinger, die mit __ anfangen und aufhören? Hab ich schon des öfteren gesehen...

Re: C-Wrapper für PureBasic

Verfasst: 30.04.2010 20:27
von NicTheQuick
Die Dinger, die mit __ beginnen oder enden sind laut Konvention "Innereien" von C++, d.h. man sollte selbst vermeiden Variablen mit zwei Unterstrichen beginnen zu lassen. Mehr ist es nicht. :wink:

Re: C-Wrapper für PureBasic

Verfasst: 30.04.2010 22:35
von Mok
Das ganze ist wohl doch etwas schwieriger als erwartet... hunderte C++ Dateien mit tausenden Funktionen, bei denen ich zu 90 % nicht weiß, wofür die überhaupt gut sind. Außerdem ist eine Archivsoftware ohne "Viewer" ziemlich suboptimal und was besseres als alle Dateien mal ins %TMP% zu kopieren und das Verzeichnis dann anzuzeigen, fällt mir irgendwie nicht ein. Und dann das ganze noch plattformübergreifend, also keine API, sondern einfach Workarounds mit der PureAPI.
Ich glaub ich muss mein Projekt jetzt begraben, hab ich mir zu einfach vorgestellt. Aber jedenfalls danke für alle Art von Hilfe.

Grüße, Mok

Re: C-Wrapper für PureBasic

Verfasst: 30.04.2010 23:13
von milan1612
Ist im Falle von 7Zip doch recht einfach Mok. Lad dir das 7Zip Source Paket runter (Link)
und kompilier dann mit Visualstudio die Projektsammlung "7z465\C\LzmaLib\LzmaLib.sln".

Raus kommt die DLL in "C:\Util\LZMA.dll" (etwas verwirrend, ich musste auch erst suchen).

In der "7z465\C\LzmaLib.h" siehst du die exportierten Funktionen...

Code: Alles auswählen

MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
  unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */
  int level,      /* 0 <= level <= 9, default = 5 */
  unsigned dictSize,  /* default = (1 << 24) */
  int lc,        /* 0 <= lc <= 8, default = 3  */
  int lp,        /* 0 <= lp <= 4, default = 0  */
  int pb,        /* 0 <= pb <= 4, default = 2  */
  int fb,        /* 5 <= fb <= 273, default = 32 */
  int numThreads /* 1 or 2, default = 2 */
  );

MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
  const unsigned char *props, size_t propsSize);
...inklusive Beschreibung der Parameter und sonstigen Informationen zur Benutzung.

Hier ist eine mit Visualstudio 2010 vorkompilierte (Release-)DLL, falls du grad keinen
Compiler zur Hand hast: http://em.q-soft.ch/files/get/VBtftKOVz2/lzma.dll


Viel Spass beim Wrappen :lol:

Re: C-Wrapper für PureBasic

Verfasst: 01.05.2010 09:48
von Mok
milan1612 hat geschrieben:Viel Spass beim Wrappen :lol:
*will-selbermachen* :mrgreen:
Nein, bin eh froh, dass ich nicht nochmals alles von Hand codieren muss :praise:

Edit: Ist ja toll, dass ich das nicht von Hand coden muss, allerdings kapier ich den Code nicht (die sollten gefälligst eine ordentliche Doc dazu machen).

Code: Alles auswählen

MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
  const unsigned char *props, size_t propsSize);
Dest ist wahrscheinlich der Pfad, wo der Archivinhalt hinkopiert werden soll, aber was ist destLen, src, srcLen, props und propsSize?
und LzmaCompress versteh ich auch nicht so ganz... :|

Re: C-Wrapper für PureBasic

Verfasst: 01.05.2010 13:09
von milan1612

Code: Alles auswählen

/*
RAM requirements for LZMA:
  for compression:   (dictSize * 11.5 + 6 MB) + state_size
  for decompression: dictSize + state_size
    state_size = (4 + (1.5 << (lc + lp))) KB
    by default (lc=3, lp=0), state_size = 16 KB.

LZMA properties (5 bytes) format
    Offset Size  Description
      0     1    lc, lp and pb in encoded form.
      1     4    dictSize (little endian).
*/

Code: Alles auswählen

/*
LzmaCompress
------------

outPropsSize -
     In:  the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
     Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.

  LZMA Encoder will use defult values for any parameter, if it is
  -1  for any from: level, loc, lp, pb, fb, numThreads
   0  for dictSize
  
level - compression level: 0 <= level <= 9;

  level dictSize algo  fb
    0:    16 KB   0    32
    1:    64 KB   0    32
    2:   256 KB   0    32
    3:     1 MB   0    32
    4:     4 MB   0    32
    5:    16 MB   1    32
    6:    32 MB   1    32
    7+:   64 MB   1    64
 
  The default value for "level" is 5.

  algo = 0 means fast method
  algo = 1 means normal method

dictSize - The dictionary size in bytes. The maximum value is
        128 MB = (1 << 27) bytes for 32-bit version
          1 GB = (1 << 30) bytes for 64-bit version
     The default value is 16 MB = (1 << 24) bytes.
     It's recommended to use the dictionary that is larger than 4 KB and
     that can be calculated as (1 << N) or (3 << N) sizes.

lc - The number of literal context bits (high bits of previous literal).
     It can be in the range from 0 to 8. The default value is 3.
     Sometimes lc=4 gives the gain for big files.

lp - The number of literal pos bits (low bits of current position for literals).
     It can be in the range from 0 to 4. The default value is 0.
     The lp switch is intended for periodical data when the period is equal to 2^lp.
     For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's
     better to set lc=0, if you change lp switch.

pb - The number of pos bits (low bits of current position).
     It can be in the range from 0 to 4. The default value is 2.
     The pb switch is intended for periodical data when the period is equal 2^pb.

fb - Word size (the number of fast bytes).
     It can be in the range from 5 to 273. The default value is 32.
     Usually, a big number gives a little bit better compression ratio and
     slower compression process.

numThreads - The number of thereads. 1 or 2. The default value is 2.
     Fast mode (algo = 0) can use only 1 thread.

Out:
  destLen  - processed output size
Returns:
  SZ_OK               - OK
  SZ_ERROR_MEM        - Memory allocation error
  SZ_ERROR_PARAM      - Incorrect paramater
  SZ_ERROR_OUTPUT_EOF - output buffer overflow
  SZ_ERROR_THREAD     - errors in multithreading functions (only for Mt version)
*/

Code: Alles auswählen

/*
LzmaUncompress
--------------
In:
  dest     - output data
  destLen  - output data size
  src      - input data
  srcLen   - input data size
Out:
  destLen  - processed output size
  srcLen   - processed input size
Returns:
  SZ_OK                - OK
  SZ_ERROR_DATA        - Data error
  SZ_ERROR_MEM         - Memory allocation arror
  SZ_ERROR_UNSUPPORTED - Unsupported properties
  SZ_ERROR_INPUT_EOF   - it needs more bytes in input buffer (src)
*/
Steht alles drin was du wissen musst :wink:


Achja, hier sind noch die Konstanten:

Code: Alles auswählen

#define SZ_OK 0

#define SZ_ERROR_DATA 1
#define SZ_ERROR_MEM 2
#define SZ_ERROR_CRC 3
#define SZ_ERROR_UNSUPPORTED 4
#define SZ_ERROR_PARAM 5
#define SZ_ERROR_INPUT_EOF 6
#define SZ_ERROR_OUTPUT_EOF 7
#define SZ_ERROR_READ 8
#define SZ_ERROR_WRITE 9
#define SZ_ERROR_PROGRESS 10
#define SZ_ERROR_FAIL 11
#define SZ_ERROR_THREAD 12

#define SZ_ERROR_ARCHIVE 16
#define SZ_ERROR_NO_ARCHIVE 17

Re: C-Wrapper für PureBasic

Verfasst: 01.05.2010 13:51
von Mok
Also, ich habe jetzt die Kontanten definiert und (versucht) LzmaCompress in PB aufzurufen, allerdings bekomme ich einen IMA bei Adresse 5

Code: Alles auswählen

PrototypeC PLzmaCompress(Dest.s, DestLen.l, Src.s, SrcLen.l, OutProps.s, OutPropsSize.l = 5, level.i = 5, DictSize.i = (1<<24), lc.i = 3, lp.i = 0, pb.i = 2, fb.i = 32, NumThreads.i = 2)

If Not OpenLibrary(0,"dll\lzma.dll")
  End
EndIf

Global LzmaCompress.PLzmaCompress = GetFunction(0,"LzmaCompress")

Debug LzmaCompress("test.lzm",FileSize("test.txt"),"test.txt",FileSize("test.txt"),"")

End
Wenn ich OutPropsSize auf 6 Stelle hab ich IMA an Adresse 6, obwohl in der Header-Datei steht "outPropsSize must be 5".
Außerdem, weiß irgendjemand, wie ich die Dateien in CPP\7zip\Archive kompiliere? In den jeweiligen Unterverzeichnissen (GZip, Rar, Cab, usw.) sind nur einige .c und einige .h Dateien drinnen, aber keine Projektdateien.

Re: C-Wrapper für PureBasic

Verfasst: 01.05.2010 14:06
von milan1612
Mok hat geschrieben:Also, ich habe jetzt die Kontanten definiert und (versucht) LzmaCompress in PB aufzurufen, allerdings bekomme ich einen IMA bei Adresse 5

Code: Alles auswählen

PrototypeC PLzmaCompress(Dest.s, DestLen.l, Src.s, SrcLen.l, OutProps.s, OutPropsSize.l = 5, level.i = 5, DictSize.i = (1<<24), lc.i = 3, lp.i = 0, pb.i = 2, fb.i = 32, NumThreads.i = 2)

If Not OpenLibrary(0,"dll\lzma.dll")
  End
EndIf

Global LzmaCompress.PLzmaCompress = GetFunction(0,"LzmaCompress")

Debug LzmaCompress("test.lzm",FileSize("test.txt"),"test.txt",FileSize("test.txt"),"")

End
Wenn ich OutPropsSize auf 6 Stelle hab ich IMA an Adresse 6, obwohl in der Header-Datei steht "outPropsSize must be 5".
"Dest" ist kurz fuer Destination und das heisst Ziel :wink:
Du uebergibst nen String aber dann nicht die Laenge des Strings sondern die einer Datei :shock:
Klar dass das nicht funktionieren kann, du musst die Datei erst in den Speicher laden und dann die Addresse
zu eben diesem Speicher uebergeben. Dest sollte ein Pointer zu von dir reserviertem Speicher mit entsprechender
Groesse sein, wie halt in der Include beschrieben. Les dir das alles nochmal genau durch und frag wenn du den
Sinn eines Parameters nicht verstehst nochmal nach. Nicht einfach raten :)
Mok hat geschrieben:Außerdem, weiß irgendjemand, wie ich die Dateien in CPP\7zip\Archive kompiliere? In den jeweiligen Unterverzeichnissen (GZip, Rar, Cab, usw.) sind nur einige .c und einige .h Dateien drinnen, aber keine Projektdateien.
Ich denke mal das ist die CPP\7zip\Archive\7z\7z.dsw.