Solved

Interfacing a dll written in c++

Posted on 2002-04-16
16
199 Views
Last Modified: 2010-05-02
Hi everyone,
I got a stupid problem again and dunno howto handle it.

I wrote a dll in VC++ the contains this function
... ImageRead(  char* fname,
                unsigned char** Image,
          int* fmt,
          int* width,
          int* height,
          int* resolution,
          int* color,
          unsigned char** map);
The first parameter is only needed to be given, the others are filled by the function.

In VB, I implemented it the following way:

Public Declare Function ImageRead Lib "myImage.dll" (ByRef fileName As Integer, _
ByRef imgData() As Byte, _
ByRef format As Integer, _
ByRef width As Integer, _
ByRef height As Integer, _
ByRef resolution As Integer, _
ByRef color As Integer, _
ByRef map() As Byte) As Long

When I try to call this function I always get a 'Runtime error 13' type mismatch.

Whats my freakin' mistake??
Thanks in advance!!!


0
Comment
Question by:ulf_k
16 Comments
 

Author Comment

by:ulf_k
ID: 6944403
Edit: Sorry, I'm stupid.
It has to be 'ByRef fileName As String'
but still I get an error 'Runtine error 49, bad dll calling convention'
Any ideas?

Greetings, Ulf.
0
 
LVL 2

Expert Comment

by:corvanderlinden
ID: 6944438
Strings are represented in C by the LPSTR data type (pointer to characters). Visual Basic can pass these parameters by using the (ByVal paramname As String) or (ByVal paramname$) conventions.
0
 
LVL 2

Expert Comment

by:skhorshid
ID: 6944457
I am not a C++ programmer but I found this example in

From talking to the author of this dll I know that you need to do somthing to be able to use a dll in VB. I believe this is an example of it but I could be wrong.


__declspec ( dllexport ) int WINAPI PlanB_E_Mail(char *server, char *emailAddr, char *fromUser, char *fromDomain, char *subject, char *xmailer, char *message );


I can email you the complete example if you like.
0
 

Expert Comment

by:clangl
ID: 6944502
I know when you are using API's you should geberally stay away from using a variable ByRef because they will generally use the adress in memory for the variable instead of the actual variable value.  What you might want to do.... Which I have never done....  use the refernces and create an object.....  I do not know if you can do that with the function you have...

That is my best shot
0
 
LVL 1

Expert Comment

by:naga1979
ID: 6944580
Dear ulf_k

If the dll written in vc++, the functions has to follow the naming convention _stdcall if you want to call it from VB. Try it. Hope this helps.

Cheers!
0
 
LVL 2

Expert Comment

by:corvanderlinden
ID: 6944644
Note

You have to use ByVal passing strings so VB can make the necessary conversions (Unicode - Ansi and so on)
0
 
LVL 18

Expert Comment

by:mdougan
ID: 6944728
To clarify a couple of things...

VB always passes strings to C or C++ dlls By Reference, even if you use the ByVal keyword.  The difference, and why it is important to use the ByVal keyword anyway, is that when you use ByVal, VB attaches a null-termination character to the end of the string, which most C or C++ functions will look for to know where the end of the string is.  Some C or C++ functions don't look for a null-termination character, and perhaps rely on the caller to pass the length of the string as another parameter, so in those cases, you'd want to pass the string ByRef.

Now, about the other things.  First, there is a difference between Visual Basic and C/C++ in their default "calling convention".  C/C++ uses the C/C++ calling convention and VB uses the "pascal" calling convention (the calling convention tells the function what order to pull the parameters off the stack).  In order to get a C/C++ dll to use the pascal calling convention it needs to be declared with the syntax shown above:

int WINAPI PlanB_E_Mail(char *server

or, I think that WINAPI is also just a constant for:

int _stdcall PlanB_E_Mail(char *server

One more thing, C++ "mangles" the name of a function when it is compiled.  So, if your function was:

PlanB(int x, int y)

Then when compiled, it will internally be renamed to something like:

PlanBIntInt

This is because C++ allows for overloading (or is it overriding) where you can have two functions with the same name but different parameters.  So, you could also have:

PlanB(int)

And that would become PlanBInt internally, allowing both functions to exist together.  If you want to make the function available to external applications, then you have to make sure that the compiler doesn't mangle the name, and the way you do this is with the Extern C declaration.  Sorry I don't have an example.
0
 
LVL 7

Expert Comment

by:Z_Beeblebrox
ID: 6944789
Hi, one of the reasons you have to pass strings ByVal not yet mentioned is that a string in VB is a pointer to the string in memory. If you pass a string ByRef, you are in fact passing a pointer to that pointer. If you pass it ByVal, then you pass the pointer itself.

HTH,

Zaphod.
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 2

Expert Comment

by:corvanderlinden
ID: 6944845
A final note on strings

Visual Basic stores strings internally as Unicode strings. When you call a DLL function, VB makes a temporary ANSI copy of the string (among others, this is terminated with a NULL character). When the function returns, it converts this temporary ANSI string back into Unicode. The problem? The DLL function receives the address of the ANSI string, which is the address of a temporary buffer. As soon as the function returns, the buffer is no longer valid. Thus, any function that obtains the address of a string by passing the string to a DLL will not return a useful value.

If you have MSDN see :
Book Excerpts - Win32 API programming with VB
0
 

Author Comment

by:ulf_k
ID: 6977015
Sorry for the l8 answer.
You all gave me some interesting points. Now it comes to the difficulty in my dll.
I declared a 'unsigned char** image' & 'unsigned char** map' in the c-interface. Anybody who can tell me, how to interface this to vb will get the 100 points. Coz I'm sitting here many hours in front of my puter, researching the web for the answer, but found nothing yet.
And many thanks to all you guys for helping me!!!

-ulf-
0
 
LVL 2

Expert Comment

by:corvanderlinden
ID: 6977061
VarPtr(var)

the address of var, returned as a long.

0
 

Author Comment

by:ulf_k
ID: 6977083
Thanx for the fast answer, but my app wont swing this way.
I call the dll function like this
dim imagedata(5000) as Byte
dim map(5000) as Byte
ret = ImageRead("c:\none.rgb", VarPtr(imagedata), format, width, height, resolution, color, VarPtr(map))

and the compiler nags me with a type mismatch error for 'VarPtr(imagedata)', so i assume there's something missing. Could you please gimme another hint?

Thanks in advance.
0
 
LVL 2

Expert Comment

by:corvanderlinden
ID: 6977130
sorry, I saw you declared them as uchar and varptr returns a long

Beats me, I'll think somemore about it
0
 
LVL 1

Expert Comment

by:mschech
ID: 6977638
Just another thought on the the string passing.
I personally like doing it:
Private Declare APIFuncW(ByVal TheString as long,...
Private Declare APIFuncA(ByVal TheString as long,...

APIFuncW(StrPtr(MyString),...)
or

ASCIIString=StrConv(MyString,vbFromUnicode)
APIFuncA(StrPtr(ASCIIString,...)


This leaves no ambiguity about exactly what is being passed.

as far as the handle passing, I think you have to do something like this:

Dim X(5000) as Byte
Dim pX as Long, hX as Long

pX=VarPtr(x(0))
hX=VarPtr(pX)
ApiFunc(VarPtr(ToX))

Arrays in VB are not like C arrays. The VarPtr of an Array
DOES NOT point to the start of the data. It points to an array descriptor. (They are "SAFEARRAYS"). ISee Curland's book, "Advanced Visual Basic 6" for a good explanation of VB internals.

Also, the above method may lead to the handle being invalid if the data is moved by the OS.  I stongly suggest you store the data in a buffer you allocate from the OS outside the VB memory management, so you can get a true handle.


0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7654106
Hi ulf_k,
It appears that you have forgotten this question. I will ask Community Support to close it unless you finalize it within 7 days. I will ask a Community Support Moderator to:

    Save as PAQ -- No Refund.

ulf_k, Please DO NOT accept this comment as an answer.
EXPERTS: Post a comment if you are certain that an expert deserves credit.  Explain why.
==========
DanRollins -- EE database cleanup volunteer
0
 

Accepted Solution

by:
SpideyMod earned 0 total points
ID: 7755103
per recommendation

SpideyMod
Community Support Moderator @Experts Exchange
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

When designing a form there are several BorderStyles to choose from, all of which can be classified as either 'Fixed' or 'Sizable' and I'd guess that 'Fixed Single' or one of the other fixed types is the most popular choice. I assume it's the most p…
Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now