?
Solved

How to call a DLL function

Posted on 2003-03-19
10
Medium Priority
?
321 Views
Last Modified: 2012-05-04
The title says DLL function, but that isn't entirely correct. I'm loading the Perl 5.8.0 DLL from a Delphi application. I'd like to pass the script a callback function in the Delphi application. I assume that adding something like callback=[pointer value] to the 'command line' would get me started. Then what?

Here's the type of function I'm thinking of:

function ScriptWantsToKnow(Question: PChar): PChar; export;

Kind regards,

Harry
0
Comment
Question by:HBosma
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
10 Comments
 
LVL 5

Expert Comment

by:Sapa
ID: 8169872
The best way to do it - write small XS stub like:

-------------------- callback.xs --------------------
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

extern __pascal char * ScriptWantsToKnow(char * question);

MODULE = Callback     PACKAGE = main

char *
ScriptWantsToKnow(question)
          char *     question

------------------------ EOF -----------------------

translate it (see perldoc xsubpp) to C program,
and add into your project. Also you need init this
XS from xs_init() function (see xs_init() example with newXS() calls in perldoc perlembed). And don't forget to pass the pointer to xs_init() functions into perl_parse().

--
Andrey

0
 

Author Comment

by:HBosma
ID: 8172935
Dear Andrey,

You've given me some homework to do. :-)

I've run your suggested .xs file through the xsubpp program. I got the following errors:

Error: 'char *' not in typemap in callback.xs, line 11
Error: 'char *' not in typemap in callback.xs, line 11
Please specify prototyping behavior for callback.xs (see perlxs manual)

This is all new to me, but my impression was that your suggested .xs file is correct. But I can't say I have a much experience with C/C++, let alone Perl when it comes to embedding / extending. Do you have any ideas?

Kind regards,

Harry
0
 
LVL 5

Expert Comment

by:Sapa
ID: 8174571
> I've run your suggested .xs file through the xsubpp
> program. I got the following errors:
>
> Error: 'char *' not in typemap in callback.xs, line 11

Just use default typemap located in the same place where xsubpp is. For example:

perl C:\Perl\lib\ExtUtils\xsubpp -prototypes -typemap C:\Perl\lib\ExtUtils\typemap callback.xs >callback.c

And you will got .C file consist of two functions - XS_main_ScriptWantsToKnow() and boot_Callback(). The first one is the .C function-wrapper (it check nubmer of passed parameters, translate perl internal string representation into pointer to char (PChar), call external ScriptWantsToKnow() function using pascal stack conventions,   translate retuned pointer into perl internal representation and push them into perl's stack as function return value), and the secont one is initializer which register this function in interpreter's tables and make it visible and callable from Perl sripts. It will be registered in 'main' namespace with 'ScriptWantsToKnow' name. After calling this initializer any Perl script running in this interpreter may call ScriptWantsToKnow() function. Also, you should write one more functions - xs_init:

perl -MExtUtils::Embed -e xsinit -- -o perlxsi.c -std Callback

after this command perlxsi.c will contain one xs_init() function with list of all embedded modules should be initialized during interpreter startup. Pointer to this function should be passed as second parameter into perl_parse() function and interpreter will initialize these modules during startup. Usually xs_init() contains also the initialization of DynaLoader module needed for many dynamic loadable modules like IO, POSIX, Fcntl etc.

--
Andrey

P.S. Of course, you can write it shorter and manually. But you wanna see good style and flexible way, right? :-)
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:HBosma
ID: 8176014
Dear Andrey,

You've given me some homework to do. :-)

I've run your suggested .xs file through the xsubpp program. I got the following errors:

Error: 'char *' not in typemap in callback.xs, line 11
Error: 'char *' not in typemap in callback.xs, line 11
Please specify prototyping behavior for callback.xs (see perlxs manual)

This is all new to me, but my impression was that your suggested .xs file is correct. But I can't say I have a much experience with C/C++, let alone Perl when it comes to embedding / extending. Do you have any ideas?

Kind regards,

Harry
0
 
LVL 5

Expert Comment

by:Sapa
ID: 8177068
You've written the same again?...
0
 

Author Comment

by:HBosma
ID: 8177088
This is helping me a lot.

I created the c files as explained. I don't have a nice C++ IDE to manage the whole project, but it should work if I merge the generated code with perllib.c, then run dmake again. I'll test this tomorrow morning (it's getting late in my part of the world).

So, how do I set the callback, how do I tell the Perl DLL where to find ScriptWantsToKnow? This almost looks to easy:

ScriptWantsToKnow = $pointer_to_func_in_exe;

(Where $pointer_to_func_in_exe would be passed to the Perl DLL as a command line argument.)

Kind regards,

Harry




0
 

Author Comment

by:HBosma
ID: 8177159
Sorry about the repost. Jugding by the time, it happened when I reloaded the page after I got the notificiation that you replied.
0
 
LVL 5

Accepted Solution

by:
Sapa earned 1600 total points
ID: 8177210
> So, how do I set the callback, how do I tell the Perl DLL where to find ScriptWantsToKnow

you should no pass pointer in command line (in any case you cannot convert raw pointer to code neither into perl function nor into the reference). After initialization this callback will be accessible from Perl scripts as regular Perl function with the same (ScriptWantsToKnow) name. If you need to get the reference to this function, do it as usually: $ref = &main::ScriptWantsToKnow;

--
Andrey
0
 

Author Comment

by:HBosma
ID: 8180469
Thanks for your last answer.

I tried to rebuild the Perl DLL. There could be a problem with the following line:

extern __pascal char * ScriptWantsToKnow(char * question);

It gave a 'Conflicting type modifiers' error. The RunPerl function in the win32 version of perllib.c is declared with DLLExport. The following got rid of the above error:

extern DllExport char * ScriptWantsToKnow(char * question);  

However, I'm stuck with a new error:

Unresolved external 'ScriptWantsToKnow(char *) referenced from E:\Source-C\Perl\Perl-5.8.0\Win32\PERLLIB.OBJ

Apparently, an implementation of the function is expected, so there must still be something wrong with the declaration.

I tried one last variation. DllExport is defined as

#if defined(PERLDLL) || defined(WIN95FIX)
#define DllExport
/*#define DllExport __declspec(dllexport)*/     /* noises with VC5+sp3 */
#else
#define DllExport __declspec(dllimport)
#endif

So, also based on what I saw elsewhere in the Perl source code, I tried simply:

DllExport char * ScriptWantsToKnow(char * question);

Same unresolved external error...

This is turning out to be more complicated than I had anticipated, so I increased the number of points for this question. I'm still a bit puzzled by what means a Perl DLL can lookup a function in a .exe. Normally, I'd have to at least export the function from the .exe, then look it up using the Windows API. I can see how the XS glue translates between different languages within the same binary, but I don't see how it manages communication between different Windows modules.

Harry
0
 

Author Comment

by:HBosma
ID: 8182119
Andrey, I think you've done quite a lot for me already. I think I need to start studying C, and then should be able to solve remaining questions myself.

Unless you have any additional insights on how a Perl DLL can magically find a function in the .exe, I'm ready to award you the points.

Harry
0

Featured Post

New benefit for Premium Members - Upgrade now!

Ready to get started with anonymous questions today? It's easy! Learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
A year or so back I was asked to have a play with MongoDB; within half an hour I had downloaded (http://www.mongodb.org/downloads),  installed and started the daemon, and had a console window open. After an hour or two of playing at the command …
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans
Suggested Courses

764 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