The online racing simulator
lib_lfsw
As much as I hate total design by community, I feel that lib_lfsw needs it otherwise I may never get around to actually finishing it.

For those who dont know what it is/was; A library of C functions (win32 atm) which could be compiled directly into, or loaded as a dll to interface with LFSWorld. I originally started work on it a few months before Christmas, and it kind of stalled as I got full time employment, etc.

Now Victor's given us a reasonably stable S2 interface to get statistics and what-not, what I want to do is what would you *like* to beable to do more easily? Lets assume that LFSWorld changes - rather than change all your code, just update lib_lfsw!

As it stands lib_lfsw is nothing more than collection of functions:
/* Generic Functions */
bool lfsw_version(char *buffer, unsigned int buffersize);
bool lfsw_author(char *buffer, unsigned int buffersize);
bool lfsw_stripcolours(char *buffer, unsigned int buffersize, char *input);
bool lfsw_code2car(char *buffer, unsigned int buffersize, unsigned char code);
bool lfsw_car2code(unsigned char buffer, char *car);
bool lfsw_code2track(char *buffer, unsigned int buffersize, char *code);
bool lfsw_track2code(char *buffer, unsigned int buffersize, char *track);
float lfsw_tracklength(char *code);
float lfsw_miles2km(float miles);
float lfsw_km2miles(float km);
/* Racer Specific functions */
unsigned int lfsw_getnumracers(lfsw_server_type type);
bool lfsw_findracer(char *buffer, unsigned int buffersize, lfsw_server_type type, char *alias);
bool lfsw_getpb(char *buffer, unsigned int buffersize, char *racer, char *track, const char carcode);
bool lfsw_getwr(char *buffer, unsigned int buffersize, char *track, const char carcode);
float lfsw_getmilesdriven(char *racer);
unsigned int lfsw_getlapsdriven(char *racer);
/* Host Specific functions */
unsigned int lfsw_getnumhosts(lfsw_server_type type);
bool lfsw_gethostinfo(lfsw_server_info &buffer, lfsw_server_type type, char *servername);
bool lfsw_probehost(char *host, unsigned int port = 63392);
/* Cache functions */
bool lfsw_refreshcache(char *filename, unsigned int timeout = 0);
bool lfsw_cachedirsexist();
bool lfsw_mkhostscache(lfsw_server_type type);
bool lfsw_mkracerscache(lfsw_server_type type);
bool lfsw_mkpbcache(char *racer);
bool lfsw_mkwrcache();
bool lfsw_dl2file(char *httpstring, char *filename);
/* Helper Functions */
bool lfsw_urlencode(char *buffer, unsigned int buffersize, char *input);
bool lfsw_dec2hex(char *buffer, unsigned int buffersize, unsigned int dec);

Lets be honest, its not as amazing as I wanted it to be, which is why I'm here.

Would you prefer it to be a pure class? If so, does anyone have experience with C++ objects being used in VB or delphi (I dont even know if its possible)? Would you like to contribute - I could CVS/SVN it easily? Do you just want me to get on with it?

Edit: I've just realised - its a framework - arrgghghghh lol, sorry I'm just fed up with frameworks atm.
if your aiming for it to be cross language then keep it as a dll

from experiance, delphi plays best with c DLLs if there made using cdecl
Yup - it was at a stage where it was being used in conjection with VB and a few other languages for testing - but as the static functions above.

What I have become more interested in is whether you can get 1 function to return an object which is then usable in other object capable languages - such as VB
you can return structs. but im not sure it will cope with passing classes back. instead of passing the class, pass a pointer to it (vb *can* do pointers)
This basically comes down to why I didnt use objects to begin with then

The C-style way of doing it above, means that the developer using lib_lfsw creates buffers - which is easy to remember to allocate and deallocate memory for - especially in VB where you dont really have to worry about it too much.

But, by returning a class from the dll the developer must remember to destroy the class properly - which is where I get worries, as I dont want to be blamed for huge memory leaks or objects going out of scope

I would prefer to use objects though
the only way i can think of at the moment to avoid the horrible buffers is to have a million and 1 structs.

for example

bool lfsw_version(char *buffer, unsigned int buffersize);

(delphi)
type
PLfswVersion = ^TLfswVersion;
TLfswVersion = Record
magor: int;
minor: int;
whatever: array[0..9] of char;
end;

function lfsw_version(): PLfswVerson;


that *should* translate into c/++ nicely

ill think of a better way tomorrow
Which is why I've got problems Do I heap the responsibility of making and loosing buffers onto "users" of lib_lfsw, or do I make extremely accurate instructions and take the risk that people will know what they're doing?

When it comes down to struct's - you're right that would clean it up, but the reason for buffers being used like that, rather than standard returning, is so that things dont go out of scope and get "lost" when memory gets overwritten. If you want struct's instead I'd still have to do something like this:
bool lfsw_version(PLfswVersion *buffer);

Plus can VB handle struct's, down to precise sizes? This is where I dont have a clue.
i dont really have a clue about vb either

the thing about using pure buffers is you will have to document the format of the buffer (what items are in what order and for what length). i dont know about you but i sure hate writing documents

and it will make more work for the end developer

eg

[copy buffer into local memory]
Move(@dest, @buffer[byte offset], length); (for some reason they named a copy procedure as move)

^^ repeat for every value
By passing the buffer to the function, wouldnt the buffer already be in the local memory of the program? i.e.
char *mybuf = new char[512];
lfsw_version(mybuf, 512);
/* Do stuff with mybuf */
delete mybuf;

Or am I missing your point?

I've got to admit, it is a lot of pain to do this. So, its probably a lot less hassle to do it as an object (defiantely less documentation writing) and hope that the end developer(s) release things properly \o/
oh i see how your doing it now

but doing it that way, what if they dont make the buffer big enough?

other then that i *guess* using buffers is the only viable solution (but a messy one )
thats why the second argue is buffer size. If its not large enough, the function returns false!

As soon as I've tidied up a bit, I'm gonna hack some new stuff together. Hopefully it might show me a solution to a small problem with C-style strings and VB.
Quote :Would you prefer it to be a pure class?

I won't use it tbh :/
IMHO C++ sucks anyway. Furthermore, whenever I was importing functions from dll written in c or c++ or some other outside-.net language by someone, it caused problems or didn't even work at all. €0.02

If that wasn't enough, that stupid dancing banana on the right is driving me crazy... I WANT RSC BACK :E
Dancing Banana on the right?! Been drinking too much today Messiah?

I'm quite willing to work with you as much as I can to make sure that its all 100% compatible, or port it to C# / anything .NET once I've written it tbh - however I cant see why you've had problems (obviously I'm look at it in the abstract).

My reasons for doing it in C / C++ (if its oop), are purely that I use ASP and some limited desktop-based .NET all day at work, and I just dont like the way it works, and also that I just like the C way of doing things. I brought myself into the coding world with JS and PHP - which are pretty C like - so its just what I prefer syntax and behaviour wise. Python is the sort of exception to this rule though :s

Edit:
To clarify, if its unclear, if I did it using OOP rather than exposing the entire class as you do with functions I'd do it like this:
void * __stdcall createLFSW()
{
return new libLFSW;
}

void __stdcall destroyLFSW(void * obj)
{
libLFSW *instance = (libLFSW *) obj;
if (instance)
delete instance;
}

Now, iirc, that passes pointers (for unmanaged objects) between c#, etc. and dll's shouldnt cause problems...
Yes, in fact there "should be" on problems but there is. Unfortunately the .NET Framework 1.1 lacks major features and support. I had really simple functions to import once, but anything I tried failed. Not at least because you don't really need "real" pointers anywhere in C# since instances of classes are passed as reference already, function returns are rather used than pointers or the ref keyword on value types (like int, double, etc).

I have asked a handful of C# programmers for advice, they were using C# nearly since it was released but didn't have a clue why it didn't work. I even had the source of the C dll :/

If I ever was using it, I had problems. The major lack I have spoken of is the reponses of the .NET Framework. For example it just gives you a NullReference Exception (Guess it's equal to null pointer exception) instead of telling you that you have used a wrong parameter while calling the function or whatelse you did just wrong. All that makes it very hard to debug. I even tried to trick the whole call with just giving a pointer to an address with only a byte array where I would be able to convert the data in their proper datatypes.

It's probably possible to use native DLLs flawlessly but it requires someone to have lots of experience with using them and using pointers and the proper datatypes. Unfortunately I lack the experience for that with C#

I don't know if that has been fixed with the .NET Framework 2.0 but I tend to doubt it, while it needs another bunch of hours to learn working with the new framework

And... there IS a banana when you write a posting, in the small window "Smilies" and it sucks as much as the "modern" -Emoticon :P
lol, I was wondering what you were on about - I've always had the emoticons disabled on quick-edit.

Hmm, I'll admit I dont know much about C# for desktop usage, but I'll ebook up, and see if I can throw some stuff together later this evening, and [hopefully] get it working.
Heh.. yeps.. I like the RSC one much more than this <insert the GREY biggrin here, the GREY one from RSC not the yellow thingie over here> forum's :/

You are going to code in C# <insert GREY biggrin here>? I bet you got your pistol ready to shoot with pointers :]

See.. when I'm reading through the thread and all about the problems you got and design decisions to make.. it's not only complicated for you but also for other users. Especially who are not familiar with C or DLLs. It may work like a charm for C/C++ programmers because they have no work with "translating" datatypes because it's the same language.

Quote :Plus can VB handle struct's, down to precise sizes?

As far as I know, yes. VB's "Type" is similar to a struct, and like C, no forward references. The only datatype missing, afaik, is the signed byte that may be put into a signed 2-byte integer datatype.

.NET can also manage the precise order of structs. I personally barely use structs and prefer classes. There's a major difference between structs in C and C#. For example, they can yield performance gain if the data chunk is <= 16 bytes in size (by Microsoft).

I think .NET programmers are somewhat spoiled. They have been given a huge framework. It may be the same like an old fashioned C/C++ programmer who got his includes ready at all times and everything works fine for him. We got our framework ready and it also works fine for us

Implementing .NET Assemblies (same like DLLs) is a lot more comfortable for us. We got intellisense providing us with all available classes, structs and their methods (even with parameters to pass) and properties to access. We don't explicitly need a list of what we can do/call and not. That's handy.

I can either provide your with support and contribute to a .NET assembly if you're going to create one or a descent article about what someone should know when moving from a C major to a C sharp ^_^ (musician joke :P). And I bet sdether would contribute as well if he got the time to do so

Otherwise I'd wrap the DLL into a C# class rather than using the DLL directly with all programs. Because you'd still need to convert the returned data into proper C# datatypes. It's less work than porting the whole functions but I guess it needs maintenance as well if the DLL changes. <insert :scratch: here>
Quote from Messiah :See.. when I'm reading through the thread and all about the problems you got and design decisions to make.. it's not only complicated for you but also for other users.

Thats exactly why I intended for this discussion. I really dont want to write something and then find out that its pointless - I want to know exactly how, if you're potentially going to use it, you'd like it to work.

Quote from Messiah :There's a major difference between structs in C and C#.

Surely they're just struct's on speed?

Quote from Messiah : For example, they can yield performance gain if the data chunk is <= 16 bytes in size (by Microsoft).

Thats really interesting to know :detective:

Quote from Messiah :Otherwise I'd wrap the DLL into a C# class rather than using the DLL directly with all programs.

This is definately more of what I initially intended, tbh, but I dont know exactly what this involves - yet

Thanks for the post Messiah - its extremely useful in helping me design something, to its maximum potential, before coding it :up:
Quote from Messiah :As far as I know, yes. VB's "Type" is similar to a struct, and like C, no forward references. The only datatype missing, afaik, is the signed byte that may be put into a signed 2-byte integer datatype.

.NET can also manage the precise order of structs. I personally barely use structs and prefer classes. There's a major difference between structs in C and C#. For example, they can yield performance gain if the data chunk is <= 16 bytes in size (by Microsoft).

What DLL are you trying to import. I know that dealing with DLLs in C# is a pain and it sure doesn't give you a clue as to why it's not working when it doesn't, but i've had pretty decent luck with using a variety of user32.dll functions, including ones that pass structs in and out. Of course this was after lots of trials and cursing. Maybe something i learned along the way can be of assistance.

Quote from Messiah :I can either provide your with support and contribute to a .NET assembly if you're going to create one or a descent article about what someone should know when moving from a C major to a C sharp ^_^ (musician joke :P). And I bet sdether would contribute as well if he got the time to do so

Otherwise I'd wrap the DLL into a C# class rather than using the DLL directly with all programs. Because you'd still need to convert the returned data into proper C# datatypes. It's less work than porting the whole functions but I guess it needs maintenance as well if the DLL changes. <insert :scratch: here>

I'm definitely in favor of wrapping whatever DLL is used in a C# class. Even when I use an outside DLL, i always write a wrapper to it. But i'm also a devout OO weenie.

I know cross-language tools can save people some work, but when you're interfacing with someone else's system, like LFSW, I find it better to have each language write the interface in a way that feels native to the language. IMHO, if I were to interface with LFSW (not on my schedule yet), I'd write it natively in C# because I'd rather have it fit directly into an object model, rather than wrap a procedural model to a third party system.

Not trying to discourage the_angry_angel's work here, I just don't think you should alter your design because of the potential use by another language. Design it the way that best fits the language of choice and anyone who wants to use it can write an adapter around it, or roll their own.
Thanks for the words, and opinions sdether - always handy to know
Quote from sdether :What DLL are you trying to import.

No win32 api. It was functions like those with structs. Also the "const char *src" confused me.

void Decompress(char *dest, const char *src, int *dest_size, int *src_size, HuffmanObj *obj);

But I simply gave up trying to use it. So I spent a bunch of hours to write my own huffman implementation in C#. Also pointed me to some list of compression algorythms, I started to write implementations for, so I unified them with an Interface ^_^
Sorry to bump, but I'm wondering what the status is on this? It would be great to get a DLL that we could all work with
Yeah TAA, get off your arse and give us a DLL or I'll be forced to unleash my really bad C skills on y'all
The status is that there is a working version in development (right now), with some basics working. I'm currently rewriting the HTTP class I'd originally written as it was slow and very testy - hopefully once thats done, its just a case of optimizing the code a tad, and releasing

With regards to threaded code - how do people feel about it?

Apologies its taking such a long time, but things are happening - it seems the time I set aside for this is getting used for other things. For instance this week/weekend the gf was ill, and I'm going down with something as well (maybe I'll take a sick day to get this down and done )
Just to let you guys know, the Thurs and Fri before the LFS UK meet I've got off work - so it means constant work on libLFSW!

Hopefully I'll have a functioning version and at least 1 warpper for a language (maybe python, or .Net).
Ooooh

/me fires up Dev-C++ in anticipation.
1

FGED GREDG RDFGDR GSFDG