Important alert: (current site time 12/18/2014 4:16:26 PM EDT)
 

winzip icon

Call CDECL DLL's - impossible?

Email
Submitted on: 11/29/2007 10:38:35 AM
By: Paul Caton 
Level: Intermediate
User Rating: By 42 Users
Compatibility: VB 5.0, VB 6.0
Views: 24926
 
     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.

 
winzip iconDownload code

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:
  1. Re-scan downloaded files using your personal virus checker before using it.
  2. NEVER, EVER run compiled files (.exe's, .ocx's, .dll's etc.)--only run source code.
  3. 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 including:McAfee.com

 
Terms of Agreement:   
By using this code, you agree to the following terms...   
  1. 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.
  2. 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.   
  3. You may link to this code from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the code or code's description.


Other 13 submission(s) by this author

 


Report Bad Submission
Use this form to tell us if this entry should be deleted (i.e contains no code, is a virus, etc.).
This submission should be removed because:

Your Vote

What do you think of this code (in the Intermediate category)?
(The code with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor (See voting log ...)
 

Other User Comments

11/9/2003 12:31:46 PMPaul Caton

Any questions?

Thanks to Mario for inspiring this submission by asking the question... can it be done?
(If this comment was disrespectful, please report it.)

 
11/9/2003 12:33:19 PMAlexandru Ionescu

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.)

 
11/9/2003 1:15:54 PMPaul Caton

Really? Da*n him, it's not the first time he's dogged my steps... and I refuse point blank to buy his book :-)
(If this comment was disrespectful, please report it.)

 
11/9/2003 4:40:52 PMDeth

another invaluable addition to the code folder, a definete keeper... here's my 5 ººººº
(If this comment was disrespectful, please report it.)

 
11/10/2003 4:25:23 AMMaRiØ G. Serrano

thks to you Paut.
I really think that this is code of the year (for me)...Simplest and effective.
(If this comment was disrespectful, please report it.)

 
11/10/2003 9:49:59 AMLight Templer

Fine 'nothing is impossible' stuff ;) ! °°°°° from me and regards! LiTe
(If this comment was disrespectful, please report it.)

 
11/10/2003 10:21:33 AM

Paul, thanx a lot for sharing. Simply fantastic and invaluable piece of code. Of course 5 globes for you.
(If this comment was disrespectful, please report it.)

 
11/10/2003 10:55:11 AMVF-fCRO

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.)

 
11/10/2003 11:14:19 AMVF-fCRO

Also FASTCALL is -WARPED CALL ECX/EDX registers use only,no push/pop waste time,blah,blah,{}... -,"much better than C_ or STDCALL"
(If this comment was disrespectful, please report it.)

 
11/10/2003 12:25:51 PMPaul Caton

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.)

 
11/10/2003 12:25:51 PMVF-fCRO

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.)

 
11/10/2003 12:36:47 PMPaul Caton

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.)

 
11/10/2003 1:00:56 PMVF-fCRO

QSORT (all of those C_ func) have port to STDCALL..(take a look inside ntdll. there is STDCALL QSORT)
(If this comment was disrespectful, please report it.)

 
11/10/2003 3:22:41 PMPaul Caton

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.)

 
11/10/2003 3:38:52 PMVlad Vissoultchev

VF-fCRO, as far as i can tell, this sample comes useful when you *have* to call exports from say w95scm.dll (SQL Server Service Control Manager) -- these are all cdecl ones.

unfortunately MS is shipping DLLs with cdecl exports which are *not* directly supported by VB declares.

HTH,
</wqw>
p.s. w95scm.dll can be found on SQL Server CD in DEVTOOLS\SAMPLES\MISC\UNZIP_MISC.EXE
(If this comment was disrespectful, please report it.)

 
11/10/2003 7:07:24 PMAlexandru Ionescu

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.)

 
11/10/2003 9:13:19 PMJatopian

Yup, once again it is proven that VB can do anything C++ can do.
(If this comment was disrespectful, please report it.)

 
11/11/2003 1:35:06 AMUnruled Boy

u r really vb guru! 5 globes!
(If this comment was disrespectful, please report it.)

 
11/14/2003 7:55:21 AMMaRiØ G. Serrano

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.)

 
11/26/2003 7:03:01 PMKenKnutson

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.)

 
12/10/2003 1:20:16 PMRoger Reeder

5 globes from me. I too, would like to see you submit a tutorial on implementing ASM with VB. Thanks again for your submissions
(If this comment was disrespectful, please report it.)

 
12/27/2003 12:37:13 PM

how about adding stdcall suport...
for dynamic runtime calling of dlls?

(If this comment was disrespectful, please report it.)

 
1/23/2004 1:17:32 PMLeontti A. Ramos M.

Great solution!!!
I had to use lameencoder in my vb projects and this brings the ideal solution for me.
(If this comment was disrespectful, please report it.)

 
2/1/2005 10:15:07 PMDavid J. Fritts

You can always use machine code/byte code for calling different calltypes (fastcall, cdecl, etc)
(If this comment was disrespectful, please report it.)

 
6/30/2005 12:16:09 PMNCrawler

One comment and a question:

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.)

 
2/11/2007 8:08:22 PMLaVolpe

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.)

 
3/30/2007 12:21:02 PMVlad Vissoultchev

Looking at Callback.asm just noticed "sub esp, patch_03" line. Should be "add esp, ..." because system stack is reversed.

Most amazing is that the qsort callback in the sample seems to work :-))

@LaVolpe & other users: this problem affects only cdecl callbacks.

cheers,
</wqw>
(If this comment was disrespectful, please report it.)

 
3/30/2007 12:34:38 PMVlad Vissoultchev

Ooops, my bad :-)) "sub esp, ..." is absolutely correct! I'm doing the opposite thunk here -- cdecl looking like stdcall.

cheers,
</wqw>
(If this comment was disrespectful, please report it.)

 
11/3/2007 7:51:48 PMTracy Dryden

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.)

 
11/27/2007 2:43:17 PMTracy Dryden

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.)

 
11/28/2007 8:00:15 PMPaul Caton

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.)

 
11/28/2007 8:06:53 PMPaul Caton

Oh, and the person above (NCrawler) who asked how to pass the address of a UDT to the CDECL function... use VarPtr(UdtInstanceName) to get the address of the UDT variable instance and pass that.

As Keith mentions (LaVolpe) above.
(If this comment was disrespectful, please report it.)

 
11/29/2007 1:36:19 PMC. Kevin Provance

Fantastic. We can always trust Paul to rediscover the holy grail. Five globes isn't enough. Thanks for your hard work bro. :-)
(If this comment was disrespectful, please report it.)

 
11/29/2007 10:46:28 PMZhu JinYong

The sorting doesn't work properly.The 3rd Column has lots of 0 at sometime.
(If this comment was disrespectful, please report it.)

 
11/30/2007 11:44:55 AMPaul Caton

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.)

 
4/6/2012 3:36:58 AMMikeB

Just Only ONE word: AWESOME
Very good job Paul.
Bravo!
(If this comment was disrespectful, please report it.)

 
9/5/2012 5:29:26 AMSteven_Jones

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.)
 

To post feedback, first please login.