LibraryMaker Desc file.
-
- Enthusiast
- Posts: 149
- Joined: Wed Apr 27, 2005 11:50 am
- Location: Adelaide, Australia
- Contact:
LibraryMaker Desc file.
I've written a C library that I'm trying to turn into a PureBASIC one, but I really don't understand the example given in the readme file. So far I have this in my PureCrypt.Desc file:
C
0
LIB
0
PureCrypt
;
; PureCrypt library descriptor
;
Now the C functions I have for the PureCrypt API are:
int SHA1Hash(char *buffer, long length, char *result);
int SHA256Hash(char *buffer, long length, char *result);
int SHA512Hash(char *buffer, long length, char *result);
int BlowfishEncode(char *password, long keylen, char *inbuf, int rounds, char *result);
int BlowfishDecode(char *password, long keylen, char *inbuf, int rounds, char *result);
int TwofishEncode(char *password, long keylen, char *inbuf, int rounds, char *result);
int TwofishDecode(char *password, long keylen, char *inbuf, int rounds, char *result);
Now how would I turn the above into something that can be understood by LibraryMaker? Do I need to rewrite anything in my C library to allow better interfacing with PB? If I can get this to work then I'm going to convert some other C libraries I've written to PureBASIC.
I have done a search on here, but have been unable to find any totally relevant information. There was one link to what sounded useful, but it no longer exists. :-/
C
0
LIB
0
PureCrypt
;
; PureCrypt library descriptor
;
Now the C functions I have for the PureCrypt API are:
int SHA1Hash(char *buffer, long length, char *result);
int SHA256Hash(char *buffer, long length, char *result);
int SHA512Hash(char *buffer, long length, char *result);
int BlowfishEncode(char *password, long keylen, char *inbuf, int rounds, char *result);
int BlowfishDecode(char *password, long keylen, char *inbuf, int rounds, char *result);
int TwofishEncode(char *password, long keylen, char *inbuf, int rounds, char *result);
int TwofishDecode(char *password, long keylen, char *inbuf, int rounds, char *result);
Now how would I turn the above into something that can be understood by LibraryMaker? Do I need to rewrite anything in my C library to allow better interfacing with PB? If I can get this to work then I'm going to convert some other C libraries I've written to PureBASIC.
I have done a search on here, but have been unable to find any totally relevant information. There was one link to what sounded useful, but it no longer exists. :-/
-
- User
- Posts: 15
- Joined: Wed Apr 27, 2005 2:55 pm
Assuming you have already generated the required LIB files successfully, here's what your desc file would look like (I'm learning too and this is a modified version of the template provided with PB) :-
Run the LibraryMaker over the above desc file and it should generate the PB lib ... however remember in the LIB, you must export the above functions using a PB_ prefix e.g. for MSVC
Code: Select all
;
; Langage used to code th library: ASM or C
C
;
; Number of windows DLL than the library need
0
; Library type (Can be OBJ or LIB)
;
LIB
;
; Number of PureBasic library needed by the library
0
; Help directory name
;
Extension1
;
; Library functions (FunctionName, Arg1, Arg2, ...)
;
SHA1Hash, String, Long, String
Long
SHA256Hash, String, Long, String
Long
SHA512Hash, String, Long, String
Long
BlowfishEncode, String, Long, String, Long, String
Long
BlowfishDecode, String, Long, String, Long, String
Long
TwofishEncode, String, Long, String, Long, String
Long
TwofishDecode, String, Long, String, Long, String
Long
Code: Select all
extern "C"
{
extern int PB_SHA1Hash(char *buffer, long length, char *result);
{
//Your code ...
}
..
..
}
-
- Enthusiast
- Posts: 229
- Joined: Wed May 14, 2003 3:38 pm
- Location: Lüneburg - Germany
I wrote down some notes some time ago, when i wrote my first PB libs.
This is based on PureBasic sample files, with some additional/modified
info for me, so i dont forget about this.
As this are notes for myself and they are some way old, i dont know if
they are correct/outdated/elegant/whatever! But my sample function
signature is matching some of your functions and maybe this is useful to
someone else.
SampleLib.c
SampleLib.Desc
SampleLib.pb
//EDIT: Typo in C Source
This is based on PureBasic sample files, with some additional/modified
info for me, so i dont forget about this.
As this are notes for myself and they are some way old, i dont know if
they are correct/outdated/elegant/whatever! But my sample function
signature is matching some of your functions and maybe this is useful to
someone else.
SampleLib.c
Code: Select all
#include <windows.h>
//////////////////////////////////////////////////////////////////////////////
// Step (1) Include PB's debugger stuff.
// With SendDebuggerError() the debugger can be stopped with some
// warning message. Useful in "_DEBUG" functions.
//////////////////////////////////////////////////////////////////////////////
extern char *PB_DEBUGGER_ErrorDescription;
extern HWND PB_DEBUGGER_Window;
extern int PB_DEBUGGER_Control;
void SendDebuggerError(char*);
void SendDebuggerError(char *text)
{
if (PB_DEBUGGER_ErrorDescription == 0)
{
PB_DEBUGGER_ErrorDescription = text;
PB_DEBUGGER_Control = 2; // Halt the PureBasic program flow...
SendMessage(PB_DEBUGGER_Window, WM_COMMAND, 6, 1);
}
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Step (2) Write the C functions you want to export to PureBasic.
// These functions must be prefixed with "PB_" for PureBasic to
// recognize them.
//
// Note: Functions have to use STDCALL calling convention.
//////////////////////////////////////////////////////////////////////////////
#define PBCOMMAND extern _stdcall
PBCOMMAND int PB_SampleCFunction(char*, long, char*);
PBCOMMAND int PB_SampleCFunction(char *buffer, long length, char *result)
{
int i;
for (i = 0; i <= length-1; i++)
{
result[i] = buffer[length-i-1];
}
return 1;
}
//////////////////////////////////////////////////////////////////////////////
// Step (3) Write the C debug functions. They must be suffixed with "_DEBUG".
// This function for example will raise an error in PB's debugger,
// if one of the three arguments are NULL (0).
//
// Note: Functions have to use CDECL calling convention and must use void
// as return value.
//////////////////////////////////////////////////////////////////////////////
#define PBDEBUG extern void
PBDEBUG PB_SampleCFunction_DEBUG(char*, long, char*);
PBDEBUG PB_SampleCFunction_DEBUG(char *buffer, long length, char *result)
{
if (!buffer)
SendDebuggerError("Error! [in] *Buffer = 0 !!");
if (!length)
SendDebuggerError("Error! [in] Lenght = 0 !!");
if (!result)
SendDebuggerError("Error! [out] *Buffer = 0 !!");
}
Code: Select all
;
; Langage used to code the library: ASM or C
C
;
; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
1
MSVCRT
;
; Library type (Can be OBJ or LIB).
LIB
;
; Number of PureBasic libraries needed by your library.
; (additional PureBasic libraries that are needed for linking).
0
;
; Help directory name.
SampleLib
;
; Library functions (FunctionName, Arg1, Arg2, ...);
; First the function name. Its the name of the C function
; that should be exported to PB, without the "PB_" Prefix
; used in C. After function name a comma and a list of
; arguments seperated by comma aswell. in parentheses
; a argument description that is showed by the PureBasic IDE
; as quick help. After the parentheses a general description
; can follow.
;
; Translation table for some arguments:
; ANSI C | PureBasic
; --------------------------
; int * | Long
; byte * | Long
; int (32 bits) | Long
; char * | Long / String
; long (32 bits) | Long
; float | Float
; double | - (must be casted to float in C for now)
; char | Byte
; void | None
; short(16 bits) | Word
;
SampleCFunction, Long, Long, Long ([in] *Buffer, [in] Length, [out] *Buffer) - My Sample Funktion.
;
; Return value:
; Type of return value and flags for:
; 'InitFunction' (a function which is called automatically
; at the start of a PureBasic program),
; 'EndFunction' (called at the end, for cleaning)
; and 'DebuggerCheck' (a debugger handler function for this command.)
Long | DebuggerCheck
Code: Select all
InBuffer$ = "foo"
Length = Len(InBuffer$)
OutBuffer$ = Space(Len(InBuffer$))
Debug SampleCFunction(@InBuffer$, Length, @OutBuffer$)
Debug OutBuffer$
; for testing debugger function
;Debug SampleCFunction(0, Length, @OutBuffer$)
Last edited by FloHimself on Thu May 19, 2005 11:23 pm, edited 1 time in total.
My favorite numbers: 09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0
-
- Enthusiast
- Posts: 149
- Joined: Wed Apr 27, 2005 11:50 am
- Location: Adelaide, Australia
- Contact:
Thanks very much for your help! It has been invaluable. Will let you know if I get it working.
Just trying it now.
Ok I have a problem. Library compiles just fine and dandy. LibMaker creates PureCrypt library and places it in the PureBASIC PureLibraries directories as it is supposed to. However when I compile the following program in PureBASIC:
; Attempt to use SHA1Hash.
InBuffer$ = "foo"
Length = Len(InBuffer$)
; Need a 20 byte buffer for the result
OutBuffer$ = Space(20)
Debug SHA1Hash(@InBuffer$, Length, @OutBuffer$)
Debug OutBuffer$
I get a PureBASIC linker error:
POLINK: warning: Multiple '.data' sections found with different flags
POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
POLINK: error: Unresolved external symbol '_PB_DEBUG_ErrorDescription'.
POLINK: error: Unresolved external symbol '_PB_DEBUG_Control'.
POLINK: error: Unresolved external symbol '_PB_DEBUG_Window'.
POLINK: error: Unresolved external symbol '___chkstk'.
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: error: Unresolved external symbol '___llshl'.
POLINK: fatal error: 7 unresolved external(s).
I'm open to any suggestions. I'm slightly hindered by 3 factors: 1) I haven't written a static library in years. 2) I've spent most of my years programming under UNIX and not windows. 3) I'm not as familiar (yet) with PureBASIC as I'd like to be. So the problem may be with the chair to keyboard interface.

Ok I have a problem. Library compiles just fine and dandy. LibMaker creates PureCrypt library and places it in the PureBASIC PureLibraries directories as it is supposed to. However when I compile the following program in PureBASIC:
; Attempt to use SHA1Hash.
InBuffer$ = "foo"
Length = Len(InBuffer$)
; Need a 20 byte buffer for the result
OutBuffer$ = Space(20)
Debug SHA1Hash(@InBuffer$, Length, @OutBuffer$)
Debug OutBuffer$
I get a PureBASIC linker error:
POLINK: warning: Multiple '.data' sections found with different flags
POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
POLINK: error: Unresolved external symbol '_PB_DEBUG_ErrorDescription'.
POLINK: error: Unresolved external symbol '_PB_DEBUG_Control'.
POLINK: error: Unresolved external symbol '_PB_DEBUG_Window'.
POLINK: error: Unresolved external symbol '___chkstk'.
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: error: Unresolved external symbol '___llshl'.
POLINK: fatal error: 7 unresolved external(s).
I'm open to any suggestions. I'm slightly hindered by 3 factors: 1) I haven't written a static library in years. 2) I've spent most of my years programming under UNIX and not windows. 3) I'm not as familiar (yet) with PureBASIC as I'd like to be. So the problem may be with the chair to keyboard interface.

-
- Enthusiast
- Posts: 149
- Joined: Wed Apr 27, 2005 11:50 am
- Location: Adelaide, Australia
- Contact:
I have at least fixed my major misunderstanding with the DEBUG_ instead of DEBUGGER_. Hmm would my Desc file still be incorrect? It isn't generating any errors, unless I remove the DebuggerCheck lines. Does it need "PB_SHA1Hash_DEBUGGER" and similar functions to be listed in the Desc file as well?
BTW could the other errors be because the functions in my library use unsigned char as opposed to char? ie. SHA1Hash(unsigned char *buffer, long length, unsigned char *result).
Still getting the following errors:
POLINK: warning: Multiple '.data' sections found with different flags
POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
(Actually why am I still getting the above error when I've updated the library with _DEBUG replaced with _DEBUGGER and then run LibraryMaker again? There is no _DEBUG function in my library anymore, only _DEBUGGER)
POLINK: error: Unresolved external symbol '___chkstk'.
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: error: Unresolved external symbol '___llshl'.
POLINK: fatal error: 4 unresolved external(s).
My Desc file:
;
; Langage used to code the library: ASM or C
C
;
; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
0
;
; Library type (Can be OBJ or LIB).
LIB
;
; Number of PureBasic libraries needed by your library.
; (additional PureBasic libraries that are needed for linking).
0
;
; Help directory name.
PureCrypt
;
; Library functions (FunctionName, Arg1, Arg2, ...);
; First the function name. Its the name of the C function
; that should be exported to PB, without the "PB_" Prefix
; used in C. After function name a comma and a list of
; arguments seperated by comma aswell. in parentheses
; a argument description that is showed by the PureBasic IDE
; as quick help. After the parentheses a general description
; can follow.
;
; Translation table for some arguments:
; ANSI C | PureBasic
; --------------------------
; int * | Long
; byte * | Long
; int (32 bits) | Long
; char * | Long / String
; long (32 bits) | Long
; float | Float
; double | - (must be casted to float in C for now)
; char | Byte
; void | None
; short(16 bits) | Word
;
; Return value:
; Type of return value and flags for:
; 'InitFunction' (a function which is called automatically
; at the start of a PureBasic program),
; 'EndFunction' (called at the end, for cleaning)
; and 'DebuggerCheck' (a debugger handler function for this command.)
;Long | DebuggerCheck
SHA1Hash, Long, Long, Long ([in] *buffer, [in] length, [out] *result) - Returns 20 byte hash.
Long | DebuggerCheck
SHA256Hash, String, Long, String ([in] *buffer, [in] length, [out] *result) - Returns 32 byte hash.
Long | DebuggerCheck
SHA512Hash, String, Long, String ([in] *buffer, [in] length, [out] *result) - 512 bit secure hash. Returns 64 byte hash.
Long | DebuggerCheck
BlowfishEncode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Blowfish encode 8 bytes. Returns 8 bytes.
Long | DebuggerCheck
BlowfishDecode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Blowfish decode 8 bytes. Returns 8 bytes.
Long | DebuggerCheck
TwofishEncode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Twofish encode 16 bytes. Returns 16 bytes.
Long | DebuggerCheck
TwofishDecode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Twofish decode 16 bytes. Returns 16 bytes.
Long | DebuggerCheck
BTW could the other errors be because the functions in my library use unsigned char as opposed to char? ie. SHA1Hash(unsigned char *buffer, long length, unsigned char *result).
Still getting the following errors:
POLINK: warning: Multiple '.data' sections found with different flags
POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
(Actually why am I still getting the above error when I've updated the library with _DEBUG replaced with _DEBUGGER and then run LibraryMaker again? There is no _DEBUG function in my library anymore, only _DEBUGGER)
POLINK: error: Unresolved external symbol '___chkstk'.
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: error: Unresolved external symbol '___llshl'.
POLINK: fatal error: 4 unresolved external(s).
My Desc file:
;
; Langage used to code the library: ASM or C
C
;
; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
0
;
; Library type (Can be OBJ or LIB).
LIB
;
; Number of PureBasic libraries needed by your library.
; (additional PureBasic libraries that are needed for linking).
0
;
; Help directory name.
PureCrypt
;
; Library functions (FunctionName, Arg1, Arg2, ...);
; First the function name. Its the name of the C function
; that should be exported to PB, without the "PB_" Prefix
; used in C. After function name a comma and a list of
; arguments seperated by comma aswell. in parentheses
; a argument description that is showed by the PureBasic IDE
; as quick help. After the parentheses a general description
; can follow.
;
; Translation table for some arguments:
; ANSI C | PureBasic
; --------------------------
; int * | Long
; byte * | Long
; int (32 bits) | Long
; char * | Long / String
; long (32 bits) | Long
; float | Float
; double | - (must be casted to float in C for now)
; char | Byte
; void | None
; short(16 bits) | Word
;
; Return value:
; Type of return value and flags for:
; 'InitFunction' (a function which is called automatically
; at the start of a PureBasic program),
; 'EndFunction' (called at the end, for cleaning)
; and 'DebuggerCheck' (a debugger handler function for this command.)
;Long | DebuggerCheck
SHA1Hash, Long, Long, Long ([in] *buffer, [in] length, [out] *result) - Returns 20 byte hash.
Long | DebuggerCheck
SHA256Hash, String, Long, String ([in] *buffer, [in] length, [out] *result) - Returns 32 byte hash.
Long | DebuggerCheck
SHA512Hash, String, Long, String ([in] *buffer, [in] length, [out] *result) - 512 bit secure hash. Returns 64 byte hash.
Long | DebuggerCheck
BlowfishEncode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Blowfish encode 8 bytes. Returns 8 bytes.
Long | DebuggerCheck
BlowfishDecode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Blowfish decode 8 bytes. Returns 8 bytes.
Long | DebuggerCheck
TwofishEncode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Twofish encode 16 bytes. Returns 16 bytes.
Long | DebuggerCheck
TwofishDecode, String, Long, String, Long, String ([in] *password, [in] keylen, [in] *inbuf, [in] rounds, [out] *result) - Twofish decode 16 bytes. Returns 16 bytes.
Long | DebuggerCheck
-
- Enthusiast
- Posts: 229
- Joined: Wed May 14, 2003 3:38 pm
- Location: Lüneburg - Germany
Nope. Don't declare the debugger functions in .desc file.Hatonastick wrote:Does it need "PB_SHA1Hash_DEBUGGER" and similar functions to be listed in the Desc file as well?
Use the "PB_DEBUGGER_" prefix for declaring the extern vars like in:Hatonastick wrote:POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
(Actually why am I still getting the above error when I've updated the library with _DEBUG replaced with _DEBUGGER and then run LibraryMaker again? There is no _DEBUG function in my library anymore, only _DEBUGGER)
Code: Select all
extern char *PB_DEBUGGER_ErrorDescription;
extern HWND PB_DEBUGGER_Window;
extern int PB_DEBUGGER_Control;
Code: Select all
PB_SHA1Hash_DEBUG(char*, long, char*);
//EDIT: like always. i'm the second poster

My favorite numbers: 09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0
Code: Select all
POLINK: error: Unresolved external symbol '___chkstk'.
Strange.
Code: Select all
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: error: Unresolved external symbol '___llshl'.
Normally they are exported as "__allshr" and "__aullshr" which is
what I don't understand. Are you using a Borland compiler by any chance?
Anyway, try this:
Code: Select all
; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
1
crtmt
Good programmers don't comment their code. It was hard to write, should be hard to read.
-
- Enthusiast
- Posts: 149
- Joined: Wed Apr 27, 2005 11:50 am
- Location: Adelaide, Australia
- Contact:
Ok, no amount of renaming of functions in the library seems to alter in any way the error messages generated by my PureBASIC test program. However having just looked at the Lcc example, I think that maybe I need to rewrite my PureBASIC API functions. The problem might be with them. Maybe. Or maybe it's the compiler I use, which is Pelles C (off shoot of Lcc). I'm definitely using __stdcall calling convention.
Tried this:
; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
1
crtmt
No change...
I deleted the copy of my PureCrypt library in the PureBASIC library directory at one stage - would that mess anything up when I redo it using LibraryMaker? Just wondering because I think it is strange that none of the changes I've made to the library seem to affect the errors in the PureBASIC program. Mind you I'm probably not thinking clearly at the moment.
I think I need sleep.
Ok, I'm going to (after some sleep) rewrite my library based upon the Lcc example provided in the Library SDK folder - which I'm guessing is still valid in regards to the current release of PureBASIC. Maybe something is messed up with how I've done the library. If that doesn't work, I'm pretty much out of ideas.
Tried this:
; Number of windows DLLs our library needs.
; This is used to tell the PureBasic compiler /
; linker which libraries are needed to link with.
1
crtmt
No change...
I deleted the copy of my PureCrypt library in the PureBASIC library directory at one stage - would that mess anything up when I redo it using LibraryMaker? Just wondering because I think it is strange that none of the changes I've made to the library seem to affect the errors in the PureBASIC program. Mind you I'm probably not thinking clearly at the moment.
I think I need sleep.

Ok, I'm going to (after some sleep) rewrite my library based upon the Lcc example provided in the Library SDK folder - which I'm guessing is still valid in regards to the current release of PureBASIC. Maybe something is messed up with how I've done the library. If that doesn't work, I'm pretty much out of ideas.
Wait a minute...Hatonastick wrote:I deleted the copy of my PureCrypt library in the PureBASIC library directory at one stage - would that mess anything up when I redo it using LibraryMaker?
When using the LibrariesMaker, your "objects path" is that of your .lib of course...
The "PureLibraries path" is set to *whatever*/PureBasic/PureLibraries/UserLibraries/, isn't it?
That way the library gets overwritten everytime anyway, so of course
it doesn't matter whether you're deleting it beforehand or not.
You're also restarting the compiler after each change to the library, right?
I'd suggest you to sleep well and re-start from scratch afterwards.
There must be something wrong in the process of building the library.
Maybe start with just one function (no debug-routine) and see what
you get.
We'll get this done, trust me!

Good programmers don't comment their code. It was hard to write, should be hard to read.
-
- Enthusiast
- Posts: 149
- Joined: Wed Apr 27, 2005 11:50 am
- Location: Adelaide, Australia
- Contact:
Yup - so I don't think the problem is the way I'm using LibraryMaker. I just tried deleting the old library out of desperation. 
Ok, I will start rewriting the library based on the Lcc example provided with the PureBASIC distribution in the Library SDK directory. I shall start with SHA1 and see how it goes. If I can get that working, the rest will be a cinch.
I'll let you know how it goes. If that doesn't work then it might be possible that Pelles C is the problem.
Actually... I think I'll just try compiling the Lcc example and see if I can get that to work first.

Ok, I will start rewriting the library based on the Lcc example provided with the PureBASIC distribution in the Library SDK directory. I shall start with SHA1 and see how it goes. If I can get that working, the rest will be a cinch.
I'll let you know how it goes. If that doesn't work then it might be possible that Pelles C is the problem.
Actually... I think I'll just try compiling the Lcc example and see if I can get that to work first.

-
- Enthusiast
- Posts: 149
- Joined: Wed Apr 27, 2005 11:50 am
- Location: Adelaide, Australia
- Contact:
Ok it's not the Pelles C compiler. I compiled the Lcc example into a library, turned it into a PureBASIC library using LibraryMaker, then ran a simple program to access the new functions and it all worked fine.
So now I'll try rewriting my library and just include the source for SHA1 hash.
Ok I have rewritten it but there are still problems when I run the test PB program mentioned above. Just generating half the number of errors.
POLINK: warning: Multiple '.data' sections found with different flags (0xc0000040 and 0x60000040).
POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
(No idea why we are still getting that one)
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: fatal error: 2 unresolved external(s).
Also I am think that maybe I should rewrite how my SHA1Hash function works. Currently it assumes that the buffer provided for the output by the PureBASIC programmer is big enough, when really I should be passing back a string or block of data from the function to PureBASIC somehow - like the StringMultiply() function in the LCCWin Library SDK example.
// Needs to be given a 20 byte buffer for the result
PBINT PB_SHA1Hash(uchar8 *buffer, ulong32 length, uchar8 *result)
{
...
return 1;
}
When it would be better to be able to do something like:
PBSTRING PB_SHA1Hash(uchar8 *buffer, ulong32 length)
{
char *result = PB_StringBase;
...
return result;
}
Although I don't quite understand how that works. Does PureBASIC somehow handle the memory allocation requests when using PB_StringBase? Hmm ok reading up on it, it's a 64kb fixed sized buffer. So I need instead to work out how to use PB_MemoryBase or similar?
I'm starting to think that maybe I should post the library source code as it is and see if anyone can spot the problem.
So now I'll try rewriting my library and just include the source for SHA1 hash.
Ok I have rewritten it but there are still problems when I run the test PB program mentioned above. Just generating half the number of errors.

POLINK: warning: Multiple '.data' sections found with different flags (0xc0000040 and 0x60000040).
POLINK: error: Unresolved external symbol '_PB_SHA1Hash_DEBUG'.
(No idea why we are still getting that one)
POLINK: error: Unresolved external symbol '___ullshr'.
POLINK: fatal error: 2 unresolved external(s).
Also I am think that maybe I should rewrite how my SHA1Hash function works. Currently it assumes that the buffer provided for the output by the PureBASIC programmer is big enough, when really I should be passing back a string or block of data from the function to PureBASIC somehow - like the StringMultiply() function in the LCCWin Library SDK example.
// Needs to be given a 20 byte buffer for the result
PBINT PB_SHA1Hash(uchar8 *buffer, ulong32 length, uchar8 *result)
{
...
return 1;
}
When it would be better to be able to do something like:
PBSTRING PB_SHA1Hash(uchar8 *buffer, ulong32 length)
{
char *result = PB_StringBase;
...
return result;
}
Although I don't quite understand how that works. Does PureBASIC somehow handle the memory allocation requests when using PB_StringBase? Hmm ok reading up on it, it's a 64kb fixed sized buffer. So I need instead to work out how to use PB_MemoryBase or similar?
I'm starting to think that maybe I should post the library source code as it is and see if anyone can spot the problem.
Last edited by Hatonastick on Fri May 20, 2005 7:17 am, edited 2 times in total.
-
- Enthusiast
- Posts: 149
- Joined: Wed Apr 27, 2005 11:50 am
- Location: Adelaide, Australia
- Contact:
The header file:
Code: Select all
///////////////////////////////////////////////////////////////////////////////
// PureCrypt v1.0a //
///////////////////////////////////////////////////////////////////////////////
// Contains library defines, macros, structures etc. //
///////////////////////////////////////////////////////////////////////////////
// Disable the following line to test your library ////////////////////////////
#define PURELIBRARY
// PureBASIC variables
#ifdef PURELIBRARY
extern HINSTANCE PB_Instance;
extern char *PB_StringBase;
#else
HINSTANCE PB_Instance;
char *PB_StringBase;
#endif
// PureBASIC debugger interface
extern char *PB_DEBUGGER_ErrorDescription;
extern HWND PB_DEBUGGER_Window;
extern int PB_DEBUGGER_Control;
static void SendDebuggerError(char *Text)
{
if (PB_DEBUGGER_ErrorDescription == 0)
{
PB_DEBUGGER_ErrorDescription = Text;
PB_DEBUGGER_Control = 2; // Halt the PureBasic program flow...
SendMessage(PB_DEBUGGER_Window, WM_COMMAND, 6, 1);
}
}
// Types and Defines //////////////////////////////////////////////////////////
typedef unsigned long long ulong64;
#define CONST64(n) n ## ULL
typedef signed long long long64;
typedef unsigned long ulong32;
typedef signed long long32;
typedef unsigned char uchar8;
// PureBASIC related defines
#define PBINT extern int _stdcall
#define PBLONG extern long32 _stdcall
#define PBSTRING extern char _stdcall *
#define PBFLOAT extern float _stdcall
#define PBDEBUG extern void
// Macros /////////////////////////////////////////////////////////////////////
// Remember that these are set for "little endian" machines
#define LOAD32H(x, y) \
{ x = ((ulong32)((y)[0] & 255)<<24) | \
((ulong32)((y)[1] & 255)<<16) | \
((ulong32)((y)[2] & 255)<<8) | \
((ulong32)((y)[3] & 255)); }
#define LOAD32L(x, y) \
memcpy(&(x), y, 4);
#define STORE32H(x, y) \
{ (y)[0] = (uchar8)(((x)>>24)&255); (y)[1] = (uchar8)(((x)>>16)&255); \
(y)[2] = (uchar8)(((x)>>8)&255); (y)[3] = (uchar8)((x)&255); }
#define STORE32L(x, y) \
{ unsigned long __t = (x); memcpy(y, &__t, 4); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
#define STORE64H(x, y) \
{ (y)[0] = (uchar8)(((x)>>56)&255); (y)[1] = (uchar8)(((x)>>48)&255); \
(y)[2] = (uchar8)(((x)>>40)&255); (y)[3] = (uchar8)(((x)>>32)&255); \
(y)[4] = (uchar8)(((x)>>24)&255); (y)[5] = (uchar8)(((x)>>16)&255); \
(y)[6] = (uchar8)(((x)>>8)&255); (y)[7] = (uchar8)((x)&255); }
#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
#define ROL64(x, y) \
( (((x)<<((ulong64)(y)&63)) | \
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define ROR64(x, y) \
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define ROL64c(x, y) \
( (((x)<<((ulong64)(y)&63)) | \
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define ROR64c(x, y) \
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define byte(x, n) (((x) >> (8 * (n))) & 255)
#undef MAX
#undef MIN
#define MAX(x, y) ( ((x)>(y))?(x):(y) )
#define MIN(x, y) ( ((x)<(y))?(x):(y) )
#define TRUE 1
#define FALSE 0
///////////////////////////////////////////////////////////////////////////////
// Cryptographic hashes //
///////////////////////////////////////////////////////////////////////////////
// SHA-1 //////////////////////////////////////////////////////////////////////
typedef struct sha1 {
ulong64 length;
ulong32 state[5];
ulong32 curlen;
uchar8 buf[64];
} SHA1;
int sha1_compress(SHA1 *md, uchar8 *buf);
int sha1_init(SHA1 *md);
int sha1_done(SHA1 *md, uchar8 *out);
int sha1_process(SHA1 *md, uchar8 *in, ulong32 inlen);
Last edited by Hatonastick on Fri May 20, 2005 5:53 am, edited 2 times in total.
-
- Enthusiast
- Posts: 149
- Joined: Wed Apr 27, 2005 11:50 am
- Location: Adelaide, Australia
- Contact:
Ignore PureCryptTables.h - it isn't important. There isn't anything in there that could be causing the problem as it's just a load of constants.
The source:
The source:
Code: Select all
///////////////////////////////////////////////////////////////////////////////
// PureCrypt v1.0a //
///////////////////////////////////////////////////////////////////////////////
// Contains library functions and library test routine. //
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <windows.h>
#include "PureCrypt.h"
#include "PureCryptTables.h"
// PureCrypt API //////////////////////////////////////////////////////////////
// Needs to be given a 20 byte buffer for the result
PBINT PB_SHA1Hash(uchar8 *buffer, ulong32 length, uchar8 *result)
{
SHA1 md;
// Have we got input?
if (buffer && *buffer && result && *result) {
if (sha1_init(&md) != TRUE)
return FALSE;
if (sha1_process(&md, buffer, length) != TRUE)
return FALSE;
if (sha1_done(&md, result) != TRUE)
return FALSE;
return TRUE;
} else {
return FALSE;
}
}
// Debugger function interface ////////////////////////////////////////////////
// --- All command debug equivalent (name + _DEBUG)
// No more '_stdcall' as the arguments aren't unstacked..
PBDEBUG PB_SHA1Hash_DEBUG(uchar8 *buffer, ulong32 length, uchar8 *result)
{
if (length == 0)
SendDebuggerError("0 length input !");
}
// SHA1 Functions /////////////////////////////////////////////////////////////
int sha1_compress(SHA1 *md, uchar8 *buf)
{
ulong32 a,b,c,d,e,W[80],i;
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32H(W[i], buf + (4*i));
}
/* copy state */
a = md->state[0];
b = md->state[1];
c = md->state[2];
d = md->state[3];
e = md->state[4];
/* expand it */
for (i = 16; i < 80; i++) {
W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
}
/* compress */
#ifdef F0
#undef F0
#endif
#define F0(x,y,z) (z ^ (x & (y ^ z)))
#ifdef FF0
#undef FF0
#endif
#define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30);
/* round one */
for (i = 0; i < 20; ) {
FF0(a,b,c,d,e,i++);
FF0(e,a,b,c,d,i++);
FF0(d,e,a,b,c,i++);
FF0(c,d,e,a,b,i++);
FF0(b,c,d,e,a,i++);
}
#ifdef F1
#undef F1
#endif
#define F1(x,y,z) (x ^ y ^ z)
#ifdef FF1
#undef FF1
#endif
#define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30);
/* round two */
for (; i < 40; ) {
FF1(a,b,c,d,e,i++);
FF1(e,a,b,c,d,i++);
FF1(d,e,a,b,c,i++);
FF1(c,d,e,a,b,i++);
FF1(b,c,d,e,a,i++);
}
#ifdef F2
#undef F2
#endif
#define F2(x,y,z) ((x & y) | (z & (x | y)))
#ifdef FF2
#undef FF2
#endif
#define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30);
/* round three */
for (; i < 60; ) {
FF2(a,b,c,d,e,i++);
FF2(e,a,b,c,d,i++);
FF2(d,e,a,b,c,i++);
FF2(c,d,e,a,b,i++);
FF2(b,c,d,e,a,i++);
}
#ifdef F3
#undef F3
#endif
#define F3(x,y,z) (x ^ y ^ z)
#ifdef FF3
#undef FF3
#endif
#define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30);
/* round four */
for (; i < 80; ) {
FF3(a,b,c,d,e,i++);
FF3(e,a,b,c,d,i++);
FF3(d,e,a,b,c,i++);
FF3(c,d,e,a,b,i++);
FF3(b,c,d,e,a,i++);
}
/* store */
md->state[0] = md->state[0] + a;
md->state[1] = md->state[1] + b;
md->state[2] = md->state[2] + c;
md->state[3] = md->state[3] + d;
md->state[4] = md->state[4] + e;
return TRUE;
}
int sha1_init(SHA1 *md)
{
int i;
if (md == NULL) return FALSE;
md->state[0] = 0x67452301UL;
md->state[1] = 0xefcdab89UL;
md->state[2] = 0x98badcfeUL;
md->state[3] = 0x10325476UL;
md->state[4] = 0xc3d2e1f0UL;
md->curlen = 0;
md->length = 0;
for (i = 0; i < 64; i++)
md->buf[i] = ' ';
return TRUE;
}
int sha1_process(SHA1 *md, uchar8 *in, ulong32 inlen)
{
ulong32 n;
int blocksize = 64;
// Check to see we have been passed valid arguments
if (md == NULL || in == NULL) {
return FALSE;
}
if (md->curlen > sizeof(md->buf)) {
return FALSE;
}
// Process block
while (inlen > 0) {
if (md->curlen == 0 && inlen >= blocksize) {
if ((sha1_compress(md, (unsigned char *)in)) != TRUE) {
return FALSE;
}
md->length += blocksize * 8;
in += blocksize;
inlen -= blocksize;
} else {
n = MIN(inlen, (blocksize - md->curlen));
memcpy(md->buf + md->curlen, in, (size_t)n);
md->curlen += n;
in += n;
inlen -= n;
if (md->curlen == blocksize) {
if ((sha1_compress(md, md->buf)) != TRUE) {
return FALSE;
}
md->length += 8*blocksize;
md->curlen = 0;
}
}
}
return TRUE;
}
int sha1_done(SHA1 *md, uchar8 *out)
{
int i;
if (md == NULL || out == NULL) {
return FALSE;
}
if (md->curlen >= sizeof(md->buf)) {
return FALSE;
}
/* increase the length of the message */
md->length += md->curlen * 8;
/* append the '1' bit */
md->buf[md->curlen++] = (unsigned char)0x80;
/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->curlen > 56) {
while (md->curlen < 64) {
md->buf[md->curlen++] = (unsigned char)0;
}
sha1_compress(md, md->buf);
md->curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->curlen < 56) {
md->buf[md->curlen++] = (unsigned char)0;
}
/* store length */
STORE64H(md->length, md->buf+56);
sha1_compress(md, md->buf);
/* copy output */
for (i = 0; i < 5; i++) {
STORE32H(md->state[i], out+(4*i));
}
return TRUE;
}
// Examples of how to interface with PureBASIC ////////////////////////////////
/*
// String return example ------------------------------------------------------------------
PBSTRING PB_StringMultiply(char *String, int NbTimes)
{
char *ResultString = PB_StringBase;
int k;
if (String && *String) // It's always good for safety and perfomance to exclude null or empty strings
{
int StringLength = strlen(String);
for (k=0; k<NbTimes; k++)
{
strcpy(PB_StringBase, String);
PB_StringBase += StringLength; // Increase the output string buffer
}
}
*PB_StringBase = 0; // Finally write the zero ending string. PB_StringBase contains the result string
return ResultString; // Returns the start of the buffer, as it has been passed
}
// Float return example --------------------------------------------------------------------
PBFLOAT PB_FloatReturn()
{
return 15.21;
}
*/
// Test library ///////////////////////////////////////////////////////////////
#ifndef PURELIBRARY
// Not done yet
int main()
{
PB_MessageBox(0, "Titre", "Text", 0);
return 0;
}
#endif
Last edited by Hatonastick on Fri May 20, 2005 5:54 am, edited 2 times in total.