`
Windows API: Basic C++ and Clarion integration 2003-04-04 -- Dan Gorrell Hello all, A number of you have contacted me and asked how to make C++ dlls which can talk to Clarion. I intended to post the solution on a webpage that I'm putting together, however it will still be some time before that's ready to go so I thought I'd just post it here. This is one way of interfacing with C++ objects from Clarion. It is by no means the only way, or even the best way, but it does work -- and it's pretty simple if you've had any experience in prototyping Windows API calls. If anyone is interested in posting alternative solutions, I'd love to see them! The C++ stuff was compiled into a standard Win32 DLL using Visual Studio .NET edition, and it works perfectly. I'm not interacting directly with the C++ objects in the Clarion code... instead I've created a set of very simple C++ procedures that talk to the objects for me. (Would you call this "unwrapping"?) I'm not sure if there's a way to get around this or not. Everything I've read so far indicates that Clarion cannot directly instantiate C++ objects... but then neither can VB, Delphi, or anything else except C++. Apparently each language handles OOP in a different way, which is pretty much ignorant of the DLL standard. (This is what I've read... I could be wrong.) So prior to COM, there was no real "standard" for handling objects across different compilers. Please bear in mind that my C++ skills are rudimentary. Also, this example is intentionally VERY simple and is quite useless. (It adds 69 to any number you pass to it) It does, however, demonstrate the basic things you would want to do with C++ objects. I can instantiate and dispose of them, I can "put" data to their properties, "get" data back, and run any methods that I need. (Each of these is demonstrated seperately.) If you want to test this solution, put the .h, .cpp, & .def files into a Win32 DLL project in C++ and compile the DLL. Clarion's LibMaker.exe will see all of the procedures that you list in the .def file and will build an appropriate .lib for you, which you can link into your Clarion project, just as you would with any DLL. // Spiffy.h typedef void* ADHandle; ADHandle newadder(); void deleteadder(ADHandle myHandle); void sbnadder(ADHandle myHandle,long myNum); void daadder(ADHandle myHandle); long gradder(ADHandle myHandle); class adder { long begnum; long endnum; public: void setBegNum(long myNum); void doAddition(); long getResult(); adder(); //Constructor ~adder(); //Destructor }; // Spiffy.cpp #include "Spiffy.h" //Functions to interface with Adder Class ADHandle newadder() { return (ADHandle) new adder; }; void deleteadder(ADHandle myHandle) { delete (adder*)myHandle; }; void sbnadder(ADHandle myHandle,long myNum) { adder *A = (adder*)myHandle; A->setBegNum(myNum); }; void daadder(ADHandle myHandle) { adder *A = (adder*)myHandle; A->doAddition(); }; long gradder(ADHandle myHandle) { adder *A = (adder*)myHandle; return A->getResult(); }; //Adder Class Implementation adder::adder(){ }; adder::~adder(){ }; VOID adder::setBegNum(LONG myNum){ begnum = myNum; }; VOID adder::doAddition(){ endnum = (begnum + 69); }; LONG adder::getResult(){ return endnum; }; // Spiffy.def LIBRARY Spiffy EXPORTS newadder deleteadder sbnadder daadder gradder That's it, so far as C++ is concerned. The first parameter that each of the C++ procedures takes is a pointer to an adder object - except for newadder() which returns one. Put those in your Visual Studio project, build a DLL, and use libmaker.exe to create a .LIB file for you. Then, add the LIB to "Library, object, and resource files" in your Clarion project and put the following in your global map. (Assuming you named the .LIB Spiffy.LIB) MODULE('Spiffy.LIB') newadder(),LONG,RAW,PASCAL deleteadder(LONG),RAW,PASCAL sbnadder(LONG,LONG),RAW,PASCAL daadder(LONG),RAW,PASCAL gradder(LONG),LONG,RAW,PASCAL END Now, create a basic window with in input field, and output field, and a button marked "add 69 using c++ object". Add the following variables to the procedure, myCPClass LONG begnum LONG endnum LONG Link begnum to the input field, endnum to the output field, and then put the following code in the accepted embed of your button. !Instantiate a new "adder" class myCPClass = newadder() !Set the beginning number property sbnadder(myCPClass,begnum) !Tell the class to perform the addition daadder(myCPClass) !Get the resulting data from the class endnum = gradder(myCPClass) !Dispose of the class deleteadder(myCPClass) DISPLAY The latent-power of C++ can now be harnessed by your Clarion programs to add 69 to any number you should choose. ;) If you wanted to get fancy, you could "re-wrap" the procedures into an object on the Clarion side so that they still looked like methods, but whether you do or don't you are interacting with C++ objects and it's a piece of cake. Best, Dan Gorrell Printed November 23, 2024, 8:15 pm This article has been viewed/printed 35335 times. Google search has resulted in 491 hits on this article since January 25, 2004. |