473,474 Members | 1,649 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Bad DLL calling convention

Made a C++ dll with MS VC6 and trying to call the dll from Excel VBA.

This is the code in the .cpp file:
#include "stdafx.h"
#include <string>
#include <math.h>

using namespace std;

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
//to compare case in-sensitive
//----------------------------
int CompareIgnoreCase(const string& s, const string& s2)
{
string::const_iterator p = s.begin(),
p2 = s2.begin();

while(p!= s.end() && p2!= s2.end()){
if(tolower(*p)!= tolower(*p2))return tolower(*p)< tolower(*p2) ? -1: 1;
++p; ++p2;
}
return s2.size()- s.size();
}
//round number n to d decimal points
//----------------------------------
double fround(double n, unsigned d)
{return floor(n * pow(10, d) + 0.5) / pow(10, d);}
double _stdcall Framingham2 (long Age,
long SysBP,
double TotChol,
double HDL,
string Sex,
string Diabetes,
string LVH,
string Smoke,
long Years = 10)
{
int x;
int btSex;
int btDiabetes;
int btLVH;
int btSmoke;
string sFEMALE = "FEMALE";
string sYES = "YES";
double dMu;
double dS;
double dU;
double dProb;

//exclude out of range input
//--------------------------
if ((Age < 35) ||
(Age > 75) ||
(SysBP < 50) ||
(SysBP > 300) ||
(TotChol < 1) ||
(TotChol > 30) ||
(HDL < 0.2) ||
(HDL > 10) ||
(Years > 10))
return 0;

x = CompareIgnoreCase(Sex,sFEMALE);
if (x == 0)
btSex = 1;
else
btSex = 0;

x = CompareIgnoreCase(Diabetes,sYES);
if (x == 0)
btDiabetes = 1;
else
btDiabetes = 0;

x = CompareIgnoreCase(LVH,sYES);
if (x == 0)
btLVH = 1;
else
btLVH = 0;

x = CompareIgnoreCase(Smoke,sYES);
if (x == 0)
btSmoke = 1;
else
btSmoke = 0;

dMu = 15.5305 +
28.4441 * btSex +
-1.4792 * log(Age) +
-14.4588 * log(Age) * btSex +
1.8515 * pow(log(Age), 2) * btSex +
-0.9119 * log(SysBP) +
-0.2767 * btSmoke +
-0.7181 * log(TotChol / HDL) +
-0.1759 * btDiabetes +
-0.1999 * btDiabetes * btSex +
-0.5865 * btLVH;

dS = exp(0.9145 + (-0.2784 * dMu));
dU = (log(Years) - dMu) / dS;
dProb = 1 - exp(-exp(dU));

return fround(dProb * 100,1);
}

I have included a .def file with this:

EXPORTS
Framingham2

It compiles (win32 release) nicely without any errors or warnings.
The function also shows nicely when I run DEPENDS.EXE.
I have checked the function in a C++ console app and that runs fine giving
the right
results. This is without input arguments though and with the values
hard-coded.

In Excel VBA I do this:

Option Explicit
Private Declare Function Framingham2 _
Lib "C:\Program Files\Microsoft Visual
Studio\MyProjects\Framingham\Release\Framingham.dl l" _
(ByVal Age As Long, _
ByVal SysBP As Long, _
ByVal TotChol As Double, _
ByVal HDL As Double, _
ByVal Sex As String, _
ByVal Diabetes As String, _
ByVal LVH As String, _
ByVal Smoke As String, _
ByVal Years As Long) As Double
Sub test()

MsgBox Framingham2(50, 140, 5.6, 1.6, "male", "no", "no", "no", 10)

End Sub

This compiles fine, but when I run Sub test() I get Run-time error 49: Badd
DLL calling convention.
I have tried altering the datatypes both in the VBA declaration and in the
..cpp file but no success.
I am completely new to this, so I am sure I have done something stupid
somewhere, but I just can't find it.
Thanks for any advice.
RBS

Apr 16 '06 #1
6 4608
RB Smissaert <ba***********@blueyonder.co.uk> wrote:
Made a C++ dll with MS VC6 and trying to call the dll from Excel VBA.
You are off-topic here, as you do not have a problem with C++, but
the your particular environment. Try comp.os.ms-windows.programmer.win32
instead.

I will answer anyway, see below for the off-topic-ness ;)
double _stdcall Framingham2 (long Age,
long SysBP,
double TotChol,
double HDL,
string Sex,
string Diabetes,
string LVH,
string Smoke,
long Years = 10) Private Declare Function Framingham2 _
Lib "C:\Program Files\Microsoft Visual
Studio\MyProjects\Framingham\Release\Framingham.dl l" _
(ByVal Age As Long, _
ByVal SysBP As Long, _
ByVal TotChol As Double, _
ByVal HDL As Double, _
ByVal Sex As String, _
ByVal Diabetes As String, _
ByVal LVH As String, _
ByVal Smoke As String, _
ByVal Years As Long) As Double
This compiles fine, but when I run Sub test() I get Run-time error
49: Badd DLL calling convention.
I have tried altering the datatypes both in the VBA declaration and
in the .cpp file but no success.


A 'string' in C++ is a C++ data type. This data-type has most
probably different representation than the VB string type, though they
effectivly hold the same information. Google for "passing C-strings to
VB" or similar. I know there was a KB article on MSDN showing how to
pass strings from VB to C Dll and back. If I remember correctly, you
have to change your function in the Dll to accept a 'char const*'
instead of 'string'. But you better look that up again.

Other than that, _stdcall should probably be __stdcall (two
underscores) .. not sure if that makes a difference tho.

hth
--
jb

(reply address in rot13, unscramble first)
Apr 16 '06 #2
Thanks for the quick reply.
Not sure I agree I am off topic here though.

I also had an inkling that doing:
#include <string>
and declaring as string in the .cpp was a bit too simple.

Will just find an example of a C++ dll that accepts
string arguments from VB and see how that is done.

RBS
"Jakob Bieling" <ar****************@rot13.com> wrote in message
news:e1*************@news.t-online.com...
RB Smissaert <ba***********@blueyonder.co.uk> wrote:
Made a C++ dll with MS VC6 and trying to call the dll from Excel VBA.


You are off-topic here, as you do not have a problem with C++, but the
your particular environment. Try comp.os.ms-windows.programmer.win32
instead.

I will answer anyway, see below for the off-topic-ness ;)
double _stdcall Framingham2 (long Age,
long SysBP,
double TotChol,
double HDL,
string Sex,
string Diabetes,
string LVH,
string Smoke,
long Years = 10)

Private Declare Function Framingham2 _
Lib "C:\Program Files\Microsoft Visual
Studio\MyProjects\Framingham\Release\Framingham.dl l" _
(ByVal Age As Long, _
ByVal SysBP As Long, _
ByVal TotChol As Double, _
ByVal HDL As Double, _
ByVal Sex As String, _
ByVal Diabetes As String, _
ByVal LVH As String, _
ByVal Smoke As String, _
ByVal Years As Long) As Double


This compiles fine, but when I run Sub test() I get Run-time error
49: Badd DLL calling convention.
I have tried altering the datatypes both in the VBA declaration and
in the .cpp file but no success.


A 'string' in C++ is a C++ data type. This data-type has most probably
different representation than the VB string type, though they effectivly
hold the same information. Google for "passing C-strings to VB" or
similar. I know there was a KB article on MSDN showing how to pass strings
from VB to C Dll and back. If I remember correctly, you have to change
your function in the Dll to accept a 'char const*' instead of 'string'.
But you better look that up again.

Other than that, _stdcall should probably be __stdcall (two
underscores) .. not sure if that makes a difference tho.

hth
--
jb

(reply address in rot13, unscramble first)


Apr 16 '06 #3
RB Smissaert <ba***********@blueyonder.co.uk> wrote:
Not sure I agree I am off topic here though.
Trust me, you are.

Neither Dlls, nor specific calling conventions are part of the
Standard C++ language. In other words, your code will not compile and
run on any other box unless it is running Windows. So your code is
platform specific, and thus leaving the realms of what is defined by
Standard C++, the topic of this group.
I also had an inkling that doing:
#include <string>
and declaring as string in the .cpp was a bit too simple.

Will just find an example of a C++ dll that accepts
string arguments from VB and see how that is done.


I checked my own code. Change your function like so

double __stdcall Framingham2 (long Age,
long SysBP,
double TotChol,
double HDL,
char const* Sex,
char const* Diabetes,
char const* LVH,
char const* Smoke,
long Years = 10)

And it should work. I know this can be tricky, so maybe there are
other things I have overlooked. In that case, please direct further
questions to comp.os.ms-windows.programmer.win32, as you will also get
better help for this problem there.

regards
--
jb

(reply address in rot13, unscramble first)
Apr 16 '06 #4
For somebody who thinks I am in the wrong group you have done a good
job in helping as you were absolutely right. Changing from string to
char const* made it all work nicely. Will just have to figure out now what
char const* exactlyt means/does and that will be it for now.
Also will have to test if this kind of dll actually is faster than running
this from VBA.
Ideally I think this should go in a .xll add-in but that would definitely be
off-topic.
Will post to the group you suggested next time if I have something similar.
Thanks again.

RBS

"Jakob Bieling" <ar****************@rot13.com> wrote in message
news:e1*************@news.t-online.com...
RB Smissaert <ba***********@blueyonder.co.uk> wrote:
Not sure I agree I am off topic here though.


Trust me, you are.

Neither Dlls, nor specific calling conventions are part of the Standard
C++ language. In other words, your code will not compile and run on any
other box unless it is running Windows. So your code is platform specific,
and thus leaving the realms of what is defined by Standard C++, the topic
of this group.
I also had an inkling that doing:
#include <string>
and declaring as string in the .cpp was a bit too simple.

Will just find an example of a C++ dll that accepts
string arguments from VB and see how that is done.


I checked my own code. Change your function like so

double __stdcall Framingham2 (long Age,
long SysBP,
double TotChol,
double HDL,
char const* Sex,
char const* Diabetes,
char const* LVH,
char const* Smoke,
long Years = 10)

And it should work. I know this can be tricky, so maybe there are other
things I have overlooked. In that case, please direct further questions to
comp.os.ms-windows.programmer.win32, as you will also get better help for
this problem there.

regards
--
jb

(reply address in rot13, unscramble first)


Apr 16 '06 #5
Just to say that putting this function in a regular C++ dll doesn't speed it
up that much. I got it about 20% faster.
Will now see if I can put this in an .xll, which I think might
be faster as it directly works with the Excel C API.

RBS

"RB Smissaert" <ba***********@blueyonder.co.uk> wrote in message
news:oH*********************@fe3.news.blueyonder.c o.uk...
Made a C++ dll with MS VC6 and trying to call the dll from Excel VBA.

This is the code in the .cpp file:
#include "stdafx.h"
#include <string>
#include <math.h>

using namespace std;

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
//to compare case in-sensitive
//----------------------------
int CompareIgnoreCase(const string& s, const string& s2)
{
string::const_iterator p = s.begin(),
p2 = s2.begin();

while(p!= s.end() && p2!= s2.end()){
if(tolower(*p)!= tolower(*p2))return tolower(*p)< tolower(*p2) ? -1: 1;
++p; ++p2;
}
return s2.size()- s.size();
}
//round number n to d decimal points
//----------------------------------
double fround(double n, unsigned d)
{return floor(n * pow(10, d) + 0.5) / pow(10, d);}
double _stdcall Framingham2 (long Age,
long SysBP,
double TotChol,
double HDL,
string Sex,
string Diabetes,
string LVH,
string Smoke,
long Years = 10)
{
int x;
int btSex;
int btDiabetes;
int btLVH;
int btSmoke;
string sFEMALE = "FEMALE";
string sYES = "YES";
double dMu;
double dS;
double dU;
double dProb;

//exclude out of range input
//--------------------------
if ((Age < 35) ||
(Age > 75) ||
(SysBP < 50) ||
(SysBP > 300) ||
(TotChol < 1) ||
(TotChol > 30) ||
(HDL < 0.2) ||
(HDL > 10) ||
(Years > 10))
return 0;

x = CompareIgnoreCase(Sex,sFEMALE);
if (x == 0)
btSex = 1;
else
btSex = 0;

x = CompareIgnoreCase(Diabetes,sYES);
if (x == 0)
btDiabetes = 1;
else
btDiabetes = 0;

x = CompareIgnoreCase(LVH,sYES);
if (x == 0)
btLVH = 1;
else
btLVH = 0;

x = CompareIgnoreCase(Smoke,sYES);
if (x == 0)
btSmoke = 1;
else
btSmoke = 0;

dMu = 15.5305 +
28.4441 * btSex +
-1.4792 * log(Age) +
-14.4588 * log(Age) * btSex +
1.8515 * pow(log(Age), 2) * btSex +
-0.9119 * log(SysBP) +
-0.2767 * btSmoke +
-0.7181 * log(TotChol / HDL) +
-0.1759 * btDiabetes +
-0.1999 * btDiabetes * btSex +
-0.5865 * btLVH;

dS = exp(0.9145 + (-0.2784 * dMu));
dU = (log(Years) - dMu) / dS;
dProb = 1 - exp(-exp(dU));

return fround(dProb * 100,1);
}

I have included a .def file with this:

EXPORTS
Framingham2

It compiles (win32 release) nicely without any errors or warnings.
The function also shows nicely when I run DEPENDS.EXE.
I have checked the function in a C++ console app and that runs fine giving
the right
results. This is without input arguments though and with the values
hard-coded.

In Excel VBA I do this:

Option Explicit
Private Declare Function Framingham2 _
Lib "C:\Program Files\Microsoft Visual
Studio\MyProjects\Framingham\Release\Framingham.dl l" _
(ByVal Age As Long, _
ByVal SysBP As Long, _
ByVal TotChol As Double, _
ByVal HDL As Double, _
ByVal Sex As String, _
ByVal Diabetes As String, _
ByVal LVH As String, _
ByVal Smoke As String, _
ByVal Years As Long) As Double
Sub test()

MsgBox Framingham2(50, 140, 5.6, 1.6, "male", "no", "no", "no", 10)

End Sub

This compiles fine, but when I run Sub test() I get Run-time error 49:
Badd DLL calling convention.
I have tried altering the datatypes both in the VBA declaration and in the
.cpp file but no success.
I am completely new to this, so I am sure I have done something stupid
somewhere, but I just can't find it.
Thanks for any advice.
RBS


Apr 16 '06 #6
OK, doing this in an .xll add-in is indeed much faster.
It timed it 30 times faster in a moderately complex
math function. This is compared with the VBA function.
Compared with the C++ dll it will be about 25 times faster.

RBS
"RB Smissaert" <ba***********@blueyonder.co.uk> wrote in message
news:Zc********************@fe3.news.blueyonder.co .uk...
Just to say that putting this function in a regular C++ dll doesn't speed
it up that much. I got it about 20% faster.
Will now see if I can put this in an .xll, which I think might
be faster as it directly works with the Excel C API.

RBS

"RB Smissaert" <ba***********@blueyonder.co.uk> wrote in message
news:oH*********************@fe3.news.blueyonder.c o.uk...
Made a C++ dll with MS VC6 and trying to call the dll from Excel VBA.

This is the code in the .cpp file:
#include "stdafx.h"
#include <string>
#include <math.h>

using namespace std;

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
//to compare case in-sensitive
//----------------------------
int CompareIgnoreCase(const string& s, const string& s2)
{
string::const_iterator p = s.begin(),
p2 = s2.begin();

while(p!= s.end() && p2!= s2.end()){
if(tolower(*p)!= tolower(*p2))return tolower(*p)< tolower(*p2) ? -1:
1;
++p; ++p2;
}
return s2.size()- s.size();
}
//round number n to d decimal points
//----------------------------------
double fround(double n, unsigned d)
{return floor(n * pow(10, d) + 0.5) / pow(10, d);}
double _stdcall Framingham2 (long Age,
long SysBP,
double TotChol,
double HDL,
string Sex,
string Diabetes,
string LVH,
string Smoke,
long Years = 10)
{
int x;
int btSex;
int btDiabetes;
int btLVH;
int btSmoke;
string sFEMALE = "FEMALE";
string sYES = "YES";
double dMu;
double dS;
double dU;
double dProb;

//exclude out of range input
//--------------------------
if ((Age < 35) ||
(Age > 75) ||
(SysBP < 50) ||
(SysBP > 300) ||
(TotChol < 1) ||
(TotChol > 30) ||
(HDL < 0.2) ||
(HDL > 10) ||
(Years > 10))
return 0;

x = CompareIgnoreCase(Sex,sFEMALE);
if (x == 0)
btSex = 1;
else
btSex = 0;

x = CompareIgnoreCase(Diabetes,sYES);
if (x == 0)
btDiabetes = 1;
else
btDiabetes = 0;

x = CompareIgnoreCase(LVH,sYES);
if (x == 0)
btLVH = 1;
else
btLVH = 0;

x = CompareIgnoreCase(Smoke,sYES);
if (x == 0)
btSmoke = 1;
else
btSmoke = 0;

dMu = 15.5305 +
28.4441 * btSex +
-1.4792 * log(Age) +
-14.4588 * log(Age) * btSex +
1.8515 * pow(log(Age), 2) * btSex +
-0.9119 * log(SysBP) +
-0.2767 * btSmoke +
-0.7181 * log(TotChol / HDL) +
-0.1759 * btDiabetes +
-0.1999 * btDiabetes * btSex +
-0.5865 * btLVH;

dS = exp(0.9145 + (-0.2784 * dMu));
dU = (log(Years) - dMu) / dS;
dProb = 1 - exp(-exp(dU));

return fround(dProb * 100,1);
}

I have included a .def file with this:

EXPORTS
Framingham2

It compiles (win32 release) nicely without any errors or warnings.
The function also shows nicely when I run DEPENDS.EXE.
I have checked the function in a C++ console app and that runs fine
giving the right
results. This is without input arguments though and with the values
hard-coded.

In Excel VBA I do this:

Option Explicit
Private Declare Function Framingham2 _
Lib "C:\Program Files\Microsoft Visual
Studio\MyProjects\Framingham\Release\Framingham.dl l" _
(ByVal Age As Long, _
ByVal SysBP As Long, _
ByVal TotChol As Double, _
ByVal HDL As Double, _
ByVal Sex As String, _
ByVal Diabetes As String, _
ByVal LVH As String, _
ByVal Smoke As String, _
ByVal Years As Long) As Double
Sub test()

MsgBox Framingham2(50, 140, 5.6, 1.6, "male", "no", "no", "no", 10)

End Sub

This compiles fine, but when I run Sub test() I get Run-time error 49:
Badd DLL calling convention.
I have tried altering the datatypes both in the VBA declaration and in
the .cpp file but no success.
I am completely new to this, so I am sure I have done something stupid
somewhere, but I just can't find it.
Thanks for any advice.
RBS


Apr 17 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Jeremy R. Harner | last post by:
I'm trying to use a DLL, but when I try to run it from Visual Basic by going to Run > Start I get a 'Bad DLL Calling Convention' error when I try to access a function inside the DLL. If I compile...
1
by: Asapi | last post by:
1. Are linkage convention and calling convention referring to the same thing? 2. Does calling convention differ between languages C and C++? 3. How does calling convention differ between...
8
by: Muthu | last post by:
I've read calling conventions to be the order(reverse or forward) in which the parameters are being read & understood by compilers. For ex. the following function. int Add(int p1, int p2, int...
1
by: Leftie | last post by:
Folks, I'm trying to call an unmanaged function from VB.NET and keep getting "Object reference not set to an instance of an object" error. The code that i wrote can be found at:...
2
by: Geler | last post by:
A theoretical question: Sorry if its a beginner question. Here is a quote from the MSDN explaning the C/C++ calling convention.. It demonstrates that the calling function is responsible to clean...
18
by: John Friedland | last post by:
My problem: I need to call (from C code) an arbitrary C library function, but I don't know until runtime what the function name is, how many parameters are required, and what the parameters are. I...
11
by: briankirkpatrick | last post by:
Forgive me if my post seems a little amateurish... I'm requesting assistance from some of you smart folks out there to get the managed calls write that meet the specification in the esa.h for...
10
by: sulekhasweety | last post by:
Hi, the following is the definition for calling convention ,which I have seen in a text book, can anyone give a more detailed explanation in terms of ANSI - C "the requirements that a...
16
by: Jaco Naude | last post by:
Hi there, This is my first post over here and I hope someone can give me some guidance. I'm trying to embed Python into a Visual C++ 2008 application and I'm getting linker problems. I've...
6
by: Ole Nielsby | last post by:
VC has a __cdecl specifier which allows functions and methods to be called with varying parameter count. (I understand this is the default for functions in general but in VC, instances use...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.