Updated November 2007, fix a DEP problem.
CDECL DLL functions cannot be called from Visual Basic... or so they'll tell you... such dll's use a incompatible technique for parameter stack cleanup. The included class uses VB+ASM to slay the "impossible" cdecl call dragon, even allowing 'C' style variable length/type parameter lists and the use of VB bas module functions as cdecl callback routines. The convention used with a cdecl function is that the caller cleans the stack on return; the stdcall convention is that the called function cleans the stack at function end. The advantage of stdcall is reduced program size, 6 calls to a function, one bit of cleanup code. The advantage of cdecl is that variable length/type parameter lists are "safe" because the caller, he who pushed the parameters onto the stack, cleans the stack... he knows exactly how many parameters he pushed and thus knows the required adjustment on function return. Years ago I worked on a team that lost a project because of our inability to speedily resolve this issue for a third-party dll - So, perhaps not the sexiest submission of the week, however, it might just save your a*s someday. The included sample demonstrates variable length/type parameter lists and callbacks routines, focusing on the std 'C' library qsort (quicksort) function.
Note: Due to the size or complexity of this submission, the author has submitted it as a .zip file to shorten your download time. Afterdownloading it, you will need a program like Winzip to decompress it.Virus note:All files are scanned once-a-day by Planet Source Code for viruses, but new viruses come
out every day, so no prevention program can catch 100% of them. For your own safety, please:
Re-scan downloaded files using your personal virus checker before using it.
NEVER, EVER run compiled files (.exe's, .ocx's, .dll's etc.)--only run source code.
Scan the source code with Minnow's Project Scanner
If you don't have a virus scanner, you can get one at many places on the net
Terms of Agreement:
By using this code, you agree to the following terms...
You may use
this code in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
You MAY NOT redistribute this code (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.
You may link to this code from another website, but ONLY if it is not wrapped in a frame.
You will abide by any additional copyright restrictions which the author may have placed in the code or code's description.
Great code as usual Paul =) I'm sure it will be very useful to lots of people...Matt Curland did this a long time ago but we had to buy his book. Now it's free and open sourced =) 5 globes! (If this comment was disrespectful, please report it.)
Calling conventions specify the way a function is called. The standard calling conventions, cdecl, place an underscore ('_') before the function name in the function's label and pass all parameters on the stack. The caller of the function must remove those arguments from the stack. Structure return values are also stored on the stack.
Conventional calling conventions are slow because they require all arguments and structure return values to be passed through memory and only 4-byte alignment is maintained.
POOOOORRRRRRRR.... (If this comment was disrespectful, please report it.)
Was that an educational statement or a submission criticism, vF-fCRO? I'm not quite sure :) Fastcall, whilst a nice idea, is of limited use because the X86 architecture has such small pool of registers. Being able to pass parameters in ecx/edx is all very well, but chances are that you're going to have to save them anyway to do so, advantage lost. (If this comment was disrespectful, please report it.)
VBVM internaly use fastcall,but only export functions are STDCALL,while complete VB code use STDCALL..There is no reason to use C_ calling,and your example is too much slow to be a serious way for external calling... I'll not give u *,if you afraid of.... (If this comment was disrespectful, please report it.)
Do you understand for who and what this is written? I'm not suggesting people use this code as a means of calling qsort, though they can if they want. - I'm providing an easy to use solution for those who are stuck with a cdecl dll and no way of calling it - What do you suggest? That they learn C and write a wrapper dll? (If this comment was disrespectful, please report it.)
VF-fCRO, thanks, but I realise that. You are still missing the point :( This is a tool for people who are stuck with a third-party CDECL DLL and no means to call it. I used MSVCRT20.dll because it should be on all systems. I used qsort to demonstrate how to use a bas module function/sub as a CDECL callback. This is not, repeat NOT, a demonstration of how to use qsort in your programs... it's an example of how to call a CDECL DLL if you need to. (If this comment was disrespectful, please report it.)
VF: What can a VB coder to do call a non-Microsoft DLL with no STCALL functionality? Such as the INFOZIP libraries? Two choices: Use Paul's great technique, or download an aditionnal 50KB wrapper written in C++, slowing down the whole process and costing ressources. (If this comment was disrespectful, please report it.)
Dear VF-fCRO I have to tell you that Paul creates this code for help me with a CDcl problem I had. I have tried to create a C Wrapper, but, it was More slowly than Paul´s code, and more difficult to create , because in the DLL i had to use, there are many functions.Well I cannot express what I think through my poor English, i only say:For me (Thnxs a lot) this is a very very good code that Paul gives to all. (If this comment was disrespectful, please report it.)
Paul, Nice going. I had a similar issue to that which you mentioned in your description where this would have saved my bacon but I ended up writing the whole thing in VB and thus slowing down the final application. This definetly goes in the 'Save Forever' code vault to be used whenever needed. Five globes and a sincere thanks. BTW: tell what's his face VF-fCRO to get a clue. This is a generalized explanation and solution with a specific example designed to let everyone see the light. Well done. (If this comment was disrespectful, please report it.)
12/6/2003 8:00:48 AM:
Outstanding!!! it's like finding the Rosetta Stone
Thank You for such an elegant solution
(If this comment was disrespectful, please report it.)
I've figured out how to convert and pass a string to a cdecl function, but what do I need to do to pass a UDT that is filled by the cdecl function? (If this comment was disrespectful, please report it.)
Paul, granted this is relatively old but your code came to my aid when I needed it. Thank you. BTW: I needed it for zLib1.DLL which has no stdCalls. You didn't mention how to pass ByRef parameters (or I couldn't find it), but I figured it out just fine: use VarPtr(paramItem) in the class' CallFunc's param array. Excellent! (If this comment was disrespectful, please report it.)
The posting may be years old, but the code is still invaluable! Instead of having to learn how to create a stdcall wrapper for a set of cdecl modules I needed to use (in the Dialogic Native Configuration Manager API), all I need was your very useful code. Thanks! (If this comment was disrespectful, please report it.)
Unfortunately, it doesn't work properly on a Windows Server 2003 system. I don't know why. It runs fine in the VB IDE, but when compiled will simply abort with an Event Log Application Error cat 100, id 1000, "Faulting Application". Doesn't do that on Win XP Pro. I'll send $25 USD to the first person that can figure out how to fix it. (If this comment was disrespectful, please report it.)
Just to note that I've found a fix for the problem that Tracy notes above and will update soon. Me being me I'm sorely tempted to redo the whole thing, unfortunately. (If this comment was disrespectful, please report it.)
Zhu, I don't think there's a problem, it's just that the random number generator sometimes produces many of the same value. Anyway, I'll be making a brand new submission to supersede this one shortly. I'll leave this submission in place for anyone that needs it. The new version can call both cdecl and stdcall functions without you, the user, needing to know what type the target function is... and also allows call by ordinal number as well as by function name. (If this comment was disrespectful, please report it.)
Amazing. (If this comment was disrespectful, please report it.)
Add Your Feedback
Your feedback will be posted below and an email sent to
the author. Please remember that the author was kind enough to
share this with you, so any criticisms must be stated politely, or they
will be deleted. (For feedback not related to this particular code, please
click here instead.)