` Printed Icetips Article

Icetips Article



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.