Link to home
Start Free TrialLog in
Avatar of OmegaJunior
OmegaJuniorFlag for United States of America

asked on

Using GetProcAddress

Greetings, C++ experts,

Sometimes I wish to expand the possibilities of Visual Basic and thus have to use API. One of the APIs I want to use is GetProcAddress. I can't get a return value other than zero. Thus my question: in which way does a C++ programmer use GetProcAddress?

I studied several MSDN examples and articles. So far this is what I found out:
Its first parameter, hModule, is the handle to a module or library, in my case returned by the LoadLibrary function.
Its second parameter, lpProcName, is the a pointer to a string value holding the name of the wanted procedure.

Now in Visual Basic we can hardly work with pointers. There are two or three functions to create pointers, but they only work if one already has the information I want to get by using GetProcAddress. Pointers are almost useless within Visual Basic. (One could also argue that all referenced parameters in VB already are pointers, but us VB programmers don't know that.) On the other hand, the GetProcAddress declaration for VB allows me to pass a string value to the second parameter instead of a pointer. That's exactly what I use.

So I created a small ocx and a small dll, both owning the same function, let's call it "Default_Function" (It's not THE default function like Dllmain, by the way, and I don't know how to get that one initialised. It should initialise automatically for dlls upon calling LoadLibrary, but I guess VB prevents that from happening). From my application I wish to call this "Default_Function" by passing the string "Default_Function" into the lpProcName parameter of GetProcAddress. Beforehand I checked for the LoadLibrary result and put that into the hModule parameter.

Still, all the GetProcAddress resulted in, was 0.

Therefore, the question once more:
How to use GetProcAddress, how to use it's parameters? Don't answer with MSDN articles, I read them and still can't get a proper result. Please answer from practice and experience.

Being very grateful,

Imagine!
Avatar of Zoppo
Zoppo
Flag of Germany image

Hi OmegaJunior,

Because only 'exported' functions or objects of a dll can be accessed from another module you have to make sure that your wanted function is exported via .DEF file or something like '__declspec(dllexport)'.

hope that helps,

ZOPPO
Avatar of OmegaJunior

ASKER

Greetings, Zoppo,

Alright, great, exporting functions of components. That's an option I don't believe VB has, and VB doesn't let us use DEF files. I'll check if there is something like an Export keyword, but I doubt it.

Thanks in advance,

Imagine!
Avatar of MDarling
MDarling

For use in Visual Basic the exported function must also have  the
pascal calling convention (__stdcall modifier)

e.g.

extern "C" int __declspec(dllexport) __stdcall YourFunc(int a,char *b)

extern "C" turns of C++ name mangling.

you don't use GetProcAddress from VB
this is what you do...

at the top of your module ...

Private Declare Function YourFunc Lib "YourDLL.dll" (A as Integer, ByVal b As String) As Integer

in any func just call as usual ...

Dim x as Integer
x=YourFunc(1,"Testing")

obviously this changes from one function to the other depending on its
prototype - which incidentally you must know!

BTW - Visual Basic does run DllMain
when your VB app first runs.

regards,
mike.
Greetings, Mike,

As you pointed out, normally one would use the declare statement in VB to access an exported function from another library.

But, in this case, I'm creating a Plug-In manager, and it is possible for someone on the other end of the world to create a plug-in. I don't know the plug-ins class, nor its object type, nor do I know the default function to call. All I know of, is that the plug-in should provide a recognizable function for my Plug-In manager.

So I can't use the declare statement. That's why I went to LoadLibrary and GetProcAddress.

Then, one could argue, why don't I use the GetObject or the CreateObject functions from VB, for all I'm doing is referencing COM objects.

True, but to use GetObject I already must have a reference, and in a plug-in architecture that is impossible, and to use CreateObject requires me to know the object type and the class of the plug-in.

To get the object type and the class I wanted to call some default function that returned these values. If there is any simpler way that works, please notify me.

As for the exporting of functions from dlls:
Did I mention I'm a VB programmer? I just checked the language reference, and we don't have export statements for functions. We can't get more global than a public declaration of a function in a public module. I can't create a Dllmain in a VB dll, and if I simply create a function called "Dllmain", it doesn't do nothing. The Sub Main does some initialisating, but only (again) when the reference already is in place.

Then, you may ask, why don't I ask this question in the VB section of EE? Answer: I did. I'm still waiting for comments there. It's just that I'm using partial C and C++ functionality, therefore a bit of help from experts on both languages is quite helpfull.

Imagine!
sorry way over my head now...

I thought you were creating a C++ DLL
for use in VB which ive had some experience of.

You can use GetProcAddress and LoadLibrary by getting them out of
kernel32.dll - its upto you then
to inform your plugin writers
of the format of the callback function
you need them to implement.

and its upto them to specify the
name of the DLL to use - maybe a registry entry that you can read???

on the point of using GetProcAddress - it really is very simple

GetProcAddress(HINSTANCE to the DLL,"Name of the function")

the problems arise when you don't get the
right name for the function...

for example you might think it is foo

but because foo is defined as
int foo(int a) we have foo exported
as _foo@4 in some cases.

this is not your problem though - since it is up to your users to export there
functions correctly.

the best way to ensure that the function
is exported correctly is to use quickview and look at the exports section.  you need to pass the string
you see in quickview to GetProcAddress
to get it working correctly.

good luck, sounds like a fun project.

regards,
mike.
OmegaJunion, does this have anything to do with C++?  it sounds like you are only using VB, right?   Then why ask the question in the C++ section?
Greetings, Mike,

and thank you very much for this comment, this is certainly something I didn't know: using the QuickView to see the exported functions. I'll check if the dll and ocx I created have any, and maybe I'll find out how to export functions in VB.

Nietod,
My last comment stated why I asked this question here, as well as in the VB section: I never worked this close to C/C++ before, so I do need input from both languages. For instance, I doubt that a VB programmer would know anything about exporting functions, or know that exported functions can be viewed with QuickView.

You must know, that VB handles all API calls as calls to C/C++ functions or routines. Therefore, the most usefull knowledge about using API comes from C/C++ experts.

Imagine!

You are creating a plug-in manager type app in VB.

What do you expect the plug-ins to be written in?

A better approach may be for every plug in to expose a common COM interface (that you define) and register in some way with your manager.
Greetings, abancroft,

It doesn't matter what language the plug-ins are written in, for I do want the programmers to use COM. And, for the plug-in to be effective the programmer must publish an interface defined by the standards of my plug-in manager.

It's just the registering I need to figure out. Even if the plug-in is COM, I can't call it unless I know its class and object type.

In the mean time, I ran into the GetClassFile function in ole32.dll. It returns the CLSID for a given filename. From there, I should be able to find the registry key holding the class and object type. I already looked in the registry and found out the key to look for is called ProgID. I didn't find a function that returns the ProgID for a CLSID or filename, so I guess I have to write one myself.

I'll let you know when this succeeds.

Imagine!
ASKER CERTIFIED SOLUTION
Avatar of abancroft
abancroft

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Greetings, abancroft,

I'm going to accept your comment as an answer. You prevented me from building a function that wouldn't work. Also, your comment directed me towards the underlying thread of how to create a plug-in manager.

To all others:
This thread of comments strayed from the original question. However the question was related to the plug-in manager subject, it was quite precise. Probable more questions related to building a plug-in manager will show up.

But I will consider this thread a dead end: GetProcAddress isn't going to work for all plug-ins. Definetely. It does work for C/C++  libraries and the likes, it won't work for VB libraries. I'm going to look for a different way. I'll have another look at the class registering functions, and see how to go from there.

Thanks to all commenters.