• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 224
  • Last Modified:

Interfacing a dll written in c++

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!!!

1 Solution
ulf_kAuthor Commented:
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.
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.
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.
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

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


You have to use ByVal passing strings so VB can make the necessary conversions (Unicode - Ansi and so on)
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:


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:


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


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
ulf_kAuthor Commented:
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!!!


the address of var, returned as a long.

ulf_kAuthor Commented:
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.
sorry, I saw you declared them as uchar and varptr returns a long

Beats me, I'll think somemore about it
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,...



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


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.

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
per recommendation

Community Support Moderator @Experts Exchange
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now