Measurement Studio for VB6

cancel
Showing results for 
Search instead for 
Did you mean: 

Why do I get 'Bad Calling Dll Convention' ?

Solved!
Go to solution

Hi,

 

the attached fiel contains an experimen to read dll made in LV 8.6 and use it in VB6.

The zip file contains the vi (adding 2 numbers), LV project, VB6 project.

 

The function seems to work.  it adds the numbers but still, it gives the error 'Bad dll calling convention'.

I think I made it right. i used the Standard Calling Conventioin.  I used Double in LV and Long in VB.

 

how do I get rid from this error?

 

Can sombody use this example on his machine.  May be it's something to do with my specific machine?

0 Kudos
Message 1 of 25
(9,877 Views)

Hello,

 

Can you give a screenshot of the error? Do you get the same thing when you use an I16?  Could you go over this devzone and try the code again? Also can you specify which version of Visual Studios you are using? Also, what version of LV were you using to build your dll?

 

 

Regards,

Andrew Eddleman

National Instruments
RIO Embedded Hardware PSE

CompactRIO Developers Guide
Message 2 of 25
(9,858 Views)
Solution
Accepted by topic author Rafi2003

VB usually gives the "bad DLL calling convention" error when you have declared a function incorrectly.  This can be as simple as exporting with __cdecl instead of __stdcall (although this will more likely just crash) or it could be that due to the function declaration being wrong, the stack gets placed in a funny state because the DLL call placed more/less data on the stack than VB expected based on your declaration.

 

In your specific case, I see a few problems.   For reference:

 

In LabVIEW, your C equivalent function prototype as shown in your project file is:

double AddNumbers(double *xY, double x, double y)

 

In VB, your declaration is:

Declare Sub AddNumbers Lib "D:\NI Projects\eDAS400\DLL\LVDLL Experiment\SharedLib.dll" _

       (ByVal x As Double, ByVal y As Double, xy As Double)

 

The first "double" in the C prototype means that the function call into the DLL is going to return a double.  In your VB prototype, by declaring it as a "Sub" you are, in essence, telling VB that you don't expect the DLL to return data.  This is one likely cause of your error.  To fix this, change it to say "Declare Function" and then add "As Double" at the end of the declaration.

 

The second problem that I see is that in your C prototype, the first parameter is being passed by reference (as a pointer).  Your VB declaration, however, is passing everything ByVal.  You need to modify this so that the parameter that returns data (xY in this case) is being passed ByRef.

 

Finally, it looks like your parameters in the C function are probably not in the order you expect.  I would expect them to be x, y, xy (as you have in the VB declaration) but the order in the C function (ie. in the DLL) isn't the same.  This will cause funny behavior.  The order should match between the two.  To fix this one, I would actually recommend changing the LV DLL so that the parameters are exported in the more logical x, y, xy order.

 

I think that this should take care of your issues.  Sorry so long winded but I wanted to make sure that you understood the "why" on this one because it can be a common error when trying to create/call DLLs from VB.

 

Jason 

Message 3 of 25
(9,832 Views)

Hi Jaicon,

 

Thank you so much for your help.  The dll is working now.

 

I made one step further and put a string as in input.  I'm trying now to display this message (actually a concatenation of this msg and another constant msg from the vi).

 

I get no errors by I get no messages.  Can you look at it please?

 

I tried to use:  C string type and Pascal string type,  Both resulted in the same way.  no response....

 

 

Thanks

Rafi

0 Kudos
Message 4 of 25
(9,808 Views)

Rafi,

 

I see your VB code but I think that you may not have included the latest version of your VI's and LabVIEW project because I don't see the string input on that side of things.

 

From a VB perspective

 

  • your strings need to be exported as C style strings and not pascal strings
  • all strings (regardless of whether they are being passed out or passed in to VB) must be passed ByVal.  Your function prototype looks correct in this regard.  Even though this may not make logical sense, there's a good explanation.  I can go into detail but the basic reasoning has to do with the fact that strings in C are typically passed as a pointer to the beginning of an array of characters terminated by a null character.  When you pass ByVal in VB, you are passing a pointer to the first character of the string (ie. to the first character in an array of characters).  Since you are passing a pointer, it works for both input and output strings.  Just like C.
  • if you are passing a string from the DLL into VB, you must pre-allocate the size of the string to be able to contain the string plus its null character.  This is a common mistake.  It looks like in your case the string is coming from VB, though, so I don't think that this is your issue.
  • I can't remember if you have to append a null character when passing from VB or if VB does it for you.  It's worth a try.  Just add "& Chr(0)" after you close the quotes to your string and see if it helps.

 

 

If all of this doesn't work, try repackaging up your zip file with all of the LV project and I'll take another look to see if there's anything obvious going on from that end. 

 

Jason 

0 Kudos
Message 5 of 25
(9,774 Views)

Hi Jason,

 

thank you so much for your help....

 

you are right, the vi was not the one I used in the project (My project pointed to the vi on my desktop).  The attached zip contains the correct vi.

 

I followed your advice to add the NULL ch. at the end of the message I'm sending to the dll.

 

No change.  Still no message is displayed by the vi.  

 

I'm not very skilled in LV, so, it is possible that I made some stupid mistake there.

 

thanks

Rafi

0 Kudos
Message 6 of 25
(9,763 Views)

Rafi,

 

I took a look at your code and I think that the problem may be in your expectation of what's going to happen.  At the point that you build into a DLL, your AddNumbers VI becomes a function call.  You are then passing a string into that function call but you don't have anything coming back out of it.

 

As an experiment, I took your VI and wired the "concatenated string" output to one of the icon terminals and then added a function export for it in the DLL function.  It looked something like the following (both the C prototype and the VB equivalent):

 

' void AddNumbers(double x, double y, char string[], double *xY, char concatenatedString[], int32_t len)

Declare Sub AddNumbers Lib "C:\Users\jasonw.AMER\Desktop\LVDLL Experiment\SharedLib.dll" _

       (ByVal x As Double, ByVal y As Double, ByVal myMsg As String, ByRef xy As Double, ByVal outString As String, ByVal stringLength As Long)

 

I then tested calling that function and I think it's safe to say that it's properly passing strings because I was able to get the returned string of "the message recevied by the dll is.....My First Message".  Here's what my calling code looked like:

 

    Dim outStr As String * 100

    Call AddNumbers(x, y, "My First Message", xy, outStr, 100)

    Debug.Print outStr

 

So I think it's working properly.  There's no need to append the null character apparently (although I did notice in your code that you had enclosed the Chr(0) in quotes...it should be without quotes to properly give a null character...but you can leave it out altogether).

 

Long story short, your code probably was working right.  Hope that helps.

 

Jason 

Message 7 of 25
(9,737 Views)

Hi Jason,

 

Thank you very very much... Your explanations are most helpful.  Not only that you figured out my problem , you also showed me how VB get a string from LV which was going to be my next step.

 

I still have a major issue here....  My expectation were to display something from LV.  What you've seen is just a practice exercise.  My objective is to perform signal analysis with LV, while VB provides some numbers and a path to a file of signal data.  The objective is to perform the analysis and, to display the graphs.

 

Did I understood you correctly, that a dll can only be used as a function call to return some value?

Is there any way to display that graph?  ... or in my experimental project, to display the text message?

 

Thanks again

Rafi

0 Kudos
Message 8 of 25
(9,727 Views)

Rafi,

 

You most certainly CAN show the front panel of the VI that you are calling.  There's an example of doing this at:

 

http://zone.ni.com/devzone/cda/epd/p/id/1887

 

It's pretty straightforward, really.   All you need to do is set the VI properties such that the front panel is shown when called.  Optionally, you can have it close when finished.  To do this, right click on the VI's icon (upper right corner of window) from either the front panel or block diagram editor and choose "VI properties".  Select the "window appearance" category and then click on the customize button.  Check the "Show front panel when called" option.  That's it!

 

Remember that from VB's perspective, it is just making a function call and that function call is going to return pretty quickly the way it's written right now.  There are LabVIEW options to leave the front panel open after the function call (in the same dialog as above).  You might also need to add some code into your VI so that there's a "Done" button or something like that.  This will cause VB to essentially hang inside of the function call until your user says that they are done with the dialog that was popped up from LabVIEW.

 

Jason 

Message 9 of 25
(9,716 Views)

Hi Jason,

 

Thank you very much. 

 

Finally i got it to work...both the string to be displayed by the dll and to return the outstring back to visual basic.

 

Thanks again

Rafi

0 Kudos
Message 10 of 25
(9,685 Views)