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

how do I call a dll not written in C/C++ within VC++

Hi guys,

I have a dll that I have written in object pascal using delphi that I want to use within my VC++ project but don't know how!

What I would like to know is the commands and declarations that I need to include and where I need to include them to be able to use these functions. So lets say my dll contained only one function
procedure mydllfunc(data:mydataType, num:ineteger)
how do I go about using this in VC++?(notice that data is a construct I made myself for the project)

thanks all,
ice
0
iceblue_22
Asked:
iceblue_22
  • 41
  • 23
  • 8
  • +1
1 Solution
 
DancerCommented:
use spyguru or any similiar program to open the dll and look at it's exports.
Use the name used there (it may have more then a few @s, letters and symbols apart from the function name) when declaring the function where I will tell you to use the "mangled" function name

let's say that your mangledfunction name was _mydllfunc@D@I
(It most probably isn't this exact name)

now, in the header, define the function (you'll have to know what each type is, my guess is that DATA turns into some pointer or something to the data structure, and num to integer (Generally, any type bigger then a DWORD will be passed by reference, i.e. pointer):

typedef void (WINAPI *DLT_mydllfunc)(SMyStruct* lpData, int nInteger)

after the typedef, create an instance of that type (preferably in some class:

class CMyClass
{
  .
  .
  .
  DLT_mydllfunc Vmydllfunc;
  .
  .
  .
}

now we load the library and initialize the function, probably in an init function or maybe (if you don't care for failiure check or if you do it another way) in the constructor.

int CMyClass::Init()
{
  //First we load the library, You should check for success in your own code
  HINSTANCE hDll = LoadLibrary("MyDll.dll");

  //Now you assign the procedure address to the variable, use mangled name here!
  Vmydllfunc = (mydllfunc)GetProcAddress(hDll,"_mydllfunc@D@I");
}

Now you can simply call the function using the call:

  CMyClass::Vmydllfunc (ddata, number);

Yours,
<><
Dancer
0
 
DancerCommented:
Sorry,
CMyClass.Vmydllfunc (ddata, number);

<><
Dancer
0
 
iceblue_22Author Commented:
Hi Dancer,

thanks dude...will try right now....and hopefully all will go well.

I just have one query. Do I need to make sure that the header declarations that I make are in the same class as the class struct declaration? ie the struct delcaration I will do in say file sapp.cpp....will I then need to make my corresponding type def in sapp.h?

thanks,

ice
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
iceblue_22Author Commented:
crap I forgot....

u talk abt a mangled version for the name of the dll....the name doesn't have any @s as I created the dll. Are these @s mandatory. wht do they represent?

ice
0
 
BorlandManCommented:

For the @s, that's what's called "Name mangling" if you have classes (C++) inside of a dll, like say MFC, the names will be mangled.

How do they name mangle? Well, it's not a standard in the industry, each compiler vendor will do it their own way, which is why MFC DLL's (dlls which have mfc objects in them) can not be used by Delphi or C++ Builder - the name mangling is different.  it looks like some people here have ideas on how to do this, but, I don't muck with that....

On the other hand, if you have created a standard DLL - say in Delphi <grin>, then you can access the functions in the dll.



If you are using standard types, it's pretty easy. Make sure you list the functions in the exports section of the dll.

However, it looks like the procedure name you included has a Object Pascal type. If that is a record type.

ex:  TMyData = record

... what else are you using in that type? If you are using any Delphi specific types, like say TDateTime, you'll have to consider those too.

I don't think the record will map perfectly to a "C" struct, You might have to change your byte alignment in the compiler settings.

also are you linking statically or are you linking dynamically using LoadLib() ??


your dll should be roughly this format:

library MyLib;

function Min(X, Y: Integer): Integer; stdcall;

begin
  if X < Y then Min := X else Min := Y;
end;


exports
  Min;

begin
end.


don't forget stdcall in function decls and also the exports section.

hopefully this will help you out a little.

sincerely,
J


0
 
iceblue_22Author Commented:
Hi J,

doesn't a cdecl directive have the same effect as stdcall??
I ask because I was under the impression that as I was going to use the dll (I made using delphi LOL)in VC++ a c declaration would be more appropriate. Rite?

this is how the declarations go:
in the main dll project file I have just an exports directive and then the functions ie:
exports
      func1,
      func2,
      ....
      ;

rite now I have an exports and cdecl directive typed after each function header in the interface section of each unit and no directives in the implementation section. Is this correct?

thanks dude,
ice
0
 
BorlandManCommented:

I would use stdCall instead.. it is supposedly more efficient... otherwise they look almost the same.... except cdecl calling convention the 'caller' of the dll cleans up and in stdcall the routine in the dll cleans up... slight difference.

but it looks like cdecl is ok.

if you have delphi, look in help under "Calling Conventions" and you can decide for yourself.

I have used Delphi dlls and called them from Visual C++ and (even) Visual Basic. I use stdcall and it has worked fine.

so, if your looking to just get it working, you might just go with stdcall  :)

another thought: you might for the fun of it (if you can afford the time), create a do nothing one liner dll, which contains the simplest function you could think of and try accessing that from C++ - just to rule out any weirdness witht the params that could be contributing to why it's not working... .just a thought.

hope that helps,
J
0
 
DancerCommented:
IceBlue_22, The declarations and all don't have to be in the same class as the caller (doesn't even have to be on the same thread).
Just include the header in the calling cpp file.

I have used this method on meny occasions in order to enable plugins fo my program, for integration with other projects written in different languages and a few times in order to use a Borland C++ dll in a VC++ project.
0
 
DancerCommented:
Oh, and the @s may not appear at all...
There are ways of making sure there's no mangling in VC and Borland C++ by declaring the function as extern "C", I don't know if there are ways in pascal/delphi but I guess there are, also, maybe they don't mangle at all.
BTW, The mangling is there to enable function overloading and classes.

<><
Dancer
0
 
iceblue_22Author Commented:
Dancer,

how/where do I put in the extern directive?

J,

did your files while calling the dll look anything like the above skeleton?

Also guys I would really like to get both your opinions on how successful you think my method will be. I have been trying to get a response from ppl who are adept at windows programming(I have no what so ever exp save for the current project). The majority think it is a very chancy thing to do. Both of you sound as though you have mastered the skill. So wht do you guys think?

Also J....yeah I do need to transfer a Object pascal data type....file....wht do you think needs to be done?

Thanks both of you for all ur help not only is it good its also prompt.......and with the project needing to be done ASAP....theres nothing more to say than that ur both champs!!

cheers
ice
0
 
SalteCommented:
Declare the function as __stdcall.

I assume that parameter types can be immediately translated to C or that you can declare structs etc that map to the object pascal data types.

Be particularly wary for pascal strings and pascal method pointers (those that Borland C++ builder refer to as __closure).

Those aren't really simple pointers but are a struct containing two pointers, a pointer to the method or function to call and a pointer to the object to use as this object for the function.

The function can also be a static function, this should be detectable by either a NULL object pointer or a pointer to the type info for the type. If static function the this pointer should not be used and the pointer should be treated like a regular function pointer.

If non-static function the function pointer is really a pointer to member function and the pointer to object is a pointer to an object that is of a type that is compatible to the type that member function is a member function of. In other words, if object is of type A and the member function is a member function of class B then either A == B or A's baseclass is B or A's baseclass' baseclass is B etc.

Alf
0
 
DancerCommented:
in c++, the extern "C" is put in the decleration of the function in the dll header/exported function decleration.

I don't think I understand your second question (maybe it is because english isn't native to me, I am hebrew.

I think if the object only has data and no functions, it should be easy enough to understand it's structure (that is, if delphi doesn't have any new radically different way of storing objects. I didn't use pascal since 1989.
Also, it should be easy enough if it does have functions.
All you need to do is make a small dll and a small program, the dll is passed an object of the wanted structure as a single parameter, and then serializes (to a file or the scree, whatever is easy for you) the object, so you can inspect what went through.
If there are functions, you probably won't be able to construct the object in C++, so to call the function you'll have to copy construct another object in the pascal side.

You'd be suprised at how often this kind of expirimenting this is done.

Yours,
<><
Dancer
0
 
BorlandManCommented:
IceBlue_22:

I may be getting confused here: You have a dll written in Delphi and you want to call it from a C/C++ application correct?  It appears that the posts above are assuming your reading a c++ builder dll ... i dunno.

As for extern "C" in your dll - there is no such thing like that in Delphi.

The skeleton did look just like what I provided.. in fact, I went and reviewed what I had done in one my dll projects and that is what it looked like.

as for how successful this will be, I don't see anything wrong with doing it.

what is the object pascal type?  Is it a TDateTime a TStringList or ???

also what is not working? Do you have a project compiling or is it that it doesnt' compile or does it crash when you make the function call or does it say it can't find the function??

I have done this before and you can do it too, don't worry.

hope this helps,
J
0
 
DancerCommented:
in c++, the extern "C" is put in the decleration of the function in the dll header/exported function decleration.

I don't think I understand your second question (maybe it is because english isn't native to me, I am hebrew.

I think if the object only has data and no functions, it should be easy enough to understand it's structure (that is, if delphi doesn't have any new radically different way of storing objects. I didn't use pascal since 1989.
Also, it should be easy enough if it does have functions.
All you need to do is make a small dll and a small program, the dll is passed an object of the wanted structure as a single parameter, and then serializes (to a file or the scree, whatever is easy for you) the object, so you can inspect what went through.
If there are functions, you probably won't be able to construct the object in C++, so to call the function you'll have to copy construct another object in the pascal side.

You'd be suprised at how often this kind of expirimenting this is done.

Yours,
<><
Dancer
0
 
SalteCommented:
cdecl is not the same as stdcall. In fact they are very different.

stdcall passes arguments in the same manner that Win32 functions accept arguments. It's a safe bet that declaring your function as stdcall in C++ will enable it to be callable from a language L using the same declaration that Win32 functions are callable from language L.

cdecl on the other hand is C's own calling standard and is VERY different. For example arguments come in the opposite order compared to stdcall. On the other hand, you can use variable number of arguments to cdecl functions. variable number of arguments is NOT available with stdcall. printf() etc are all __cdecl. The vprintf() functions etc doesn't have to be __cdecl since they are called with regular arguments. I believe they usually are though - not sure about that.

stdcall is the 'lingua franca' among calling styles on Win32 platforms. Use stdcall, it is available in most languages on Win32 platforms and all languages that can call DLL functions. This is because most DLL's are defined using __stdcall and in particular kernel32.exe, user32.exe and gui32.exe have almost all their functions defined as __stdcall and those that aren't are not available from any language unless  that language can declare a function to be __cdecl. Object pascal happen to have cdecl as a keyword and can define functions as cdecl but there's no reason why you should do that.

Alf
0
 
iceblue_22Author Commented:
Hi Dancer,
 
I think I am going to give the extern a miss and stick with how I am doing it right now...thts not too much of a hassel rite?

Hi Alf,
thanks for clearing tht up for me....I am going to change all my cdecl into stdcall's right now.

Hi J,

The typedef that I am having problems with is this:
void DecodeJPEG(lStream: TMemoryStream; lOutSmallRA: SmallIntP0; lImgRAz: ByteP0;lOutputSz,lCptPosition,lCptSize: integer; lVerbose: BOOL);  
In the above I don't know how to represent parameter lStream as it is type TMemoryStream...would you have any clue as to how to do this? Also type SmallIntPO and BytePO are custom made types in delphi...wht would you suggest i do...I have been referring to these as pointers....is this ok? so for example if I had:
 void func1(var1:BytePO; var2:SmallInoPO);
I would convert this into a typedef as follows
 typedef void (WINAPI *DLTfunc1)(BytePO* var1, SmallIntPO* var2)
and in class MyClass I have a corresponding
  .....
  DLTfunc1 func_1;
  .....

What is happening is that though I can get both the dll and the C header files to compile the functions don't seem to work!!!...i don't knw if it because I have written the dll incorrectly or if I am calling the dll functions incorrectly......

thanks all
ice
0
 
iceblue_22Author Commented:
Also u guys,

My initial 20 points don't do justice to the help you've given me......so please let me know on a more likely number bearing in mind tht u'll have to share them....can u do tht?

later,
ice
0
 
iceblue_22Author Commented:
also J,

what about type file?? how would I declare it an array?...can I do this?

ice
0
 
BorlandManCommented:

Hi,
a few thoughts/comments.  First, I apologize if I didn't emphasize it enough, but in my first post, I suggested you go with stdcall instead of cdecl and that although i didn't have the gory differences, I mentioned help file, and that I thought you should just go with stdcall

regarding your Delphi specific types, I would move away from them.

void DecodeJPEG(lStream: TMemoryStream; lOutSmallRA: SmallIntP0; lImgRAz: ByteP0;lOutputSz,lCptPosition,lCptSize: integer; lVerbose: BOOL);  

as for SmallIntPO, what do you have that declared as? Also your lOutputSz is integer, but it the way you named it, it looks like it should be a pchar...

the TMemoryStream, I'm not sure what to do about that, let me go eat dinner and think about it...

as for points.... I don't even bother to track points much.. was it only 20?  Yeh, you might crank that up some.

J
0
 
iceblue_22Author Commented:
Another query Dancer,

in the above skeleton that u have given me:
    //Now you assign the procedure address to the variable, use mangled name here!
 Vmydllfunc = (mydllfunc)GetProcAddress(hDll,"_mydllfunc@D@I");

where does the (mydllfunc)Get.... come from ie which name am I supposed to use?

ice
0
 
iceblue_22Author Commented:
Another query Dancer,

in the above skeleton that u have given me:
    //Now you assign the procedure address to the variable, use mangled name here!
 Vmydllfunc = (mydllfunc)GetProcAddress(hDll,"_mydllfunc@D@I");

where does the (mydllfunc)Get.... come from ie which name am I supposed to use?

ice
0
 
BorlandManCommented:

You can link to dlls 2 ways
1. using load time dynamic linking
2. using run-time dynamic linking


for load-time dynamic linking, you need to link in a .lib file, which has the information about the dll.

for run-time dynamic linking, you use the LoadLib() function and a few others to dynamically make a call to the dll at runtime.

Here's a sample of calling a dll. I'm in a hurry right now, so I stole it from a sample...  for this purpose, let's pretend that you have a dll called MyDll.dll

it contains one function, called void puts( char* psz);

to call that function in our pretend dll, you sould could use the following code (courtesy of a microsoft sample)

look this over and I think you'll get a better idea of how you call it.

hth ,
J

 
#include <stdio.h>
#include <windows.h>
 
typedef VOID (*MYPROC)(LPTSTR);

 
VOID main(VOID)
{
    HINSTANCE hinstLib;
    MYPROC ProcAdd;
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
 
    // Get a handle to the DLL module.

    hinstLib = LoadLibrary("myputs");
 
    // If the handle is valid, try to get the function
    // address.
 
    if (hinstLib != NULL)
    {
        ProcAdd = (MYPROC) GetProcAddress
            (hinstLib, "myPuts");
 
        // If the function address is valid, call the
        // function.
 
        if (fRunTimeLinkSuccess = (ProcAdd != NULL))
            (ProcAdd) ("message via DLL function\n");
 
        // Free the DLL module.
 
        fFreeResult = FreeLibrary(hinstLib);
    }
 
    // If unable to call the DLL function, use an
    // alternative.
 
    if (! fRunTimeLinkSuccess)
        printf("message via alternative method\n");
}

0
 
iceblue_22Author Commented:
J...HELP!!!....

first off...please knw that all you help is much appreciated.......having said that help me!!!

I compiled the header file and I get 103 errors for 20 lines of code.....most of them come from the pointer declarations of the delphi custom made types. And also something about bool type usage:
   'bool' : illegal use of this type as an expression

also id having the particular dll within the same directory as the project enough for VC++ to link the dll with the project?

waiting in trepridation,
ice
0
 
BorlandManCommented:
Ok, I'm back.

what header file did you compile? I guess a file you created to map to the types for Delphi?

Ok for the memory stream, I thought about this some and I don't think you'll be able to get away with moving that between c++ and delphi - unless maybe your using C++ Builder (heh heh)... I have the feeling your using Visual C++ right?.. so that is ruled out.

what you might consider doing is creating a set of functions in the dll, which you can call to perform operations on the MemoryStream - which is living inside the dll. Kind of like manipulating windows with the Windows API, you have a set of functions, which you call and they all operate on a Windows Handle (HWND). You might be able to do the same thing with the MemoryStream - this way you wouldn't have to worry about passing it back and forth... thus solving that problem.

as for the other types...  please provide me with the record as you have declared it in Delphi and the types you used in the record if they are not standard types.

I'm putting together a little sample, which will help, hold on.

J

0
 
BorlandManCommented:
oh yeh, you get a compiler error for 'bool' because
c++ doesn't know about that type.

You need to declare your bool as BOOL
case matters.

J
0
 
iceblue_22Author Commented:
J...ur a legend...

right now I have about 8 errors....I figured out the prob with bool...but wht is pissing me off right now is the followig error....
error C2320: expected ':' to follow access specifier 'type'
and
fatal error C1070: mismatched #if/#endif pair in file 'sapp.dll'

both of these I can't figure out. Also in relation to the delphi data types what I have done is written up C struct that hold the same information.

for error C2320 I have done the following say my function is Display_Image...then

typedef void (WINAPI *DLT_DisplayImage)(bool lUpdateCon, bool lForceDraw, int lSlice, double lInWinWid, double lInWinCen);
 and
class sappdll
{
//Construction
public
     
DLT_DisplayImage  Display_Image_dll;
}

is this right?

ice
0
 
iceblue_22Author Commented:
J...ur a legend...

right now I have about 8 errors....I figured out the prob with bool...but wht is pissing me off right now is the followig error....
error C2320: expected ':' to follow access specifier 'type'
and
fatal error C1070: mismatched #if/#endif pair in file 'sapp.dll'

both of these I can't figure out. Also in relation to the delphi data types what I have done is written up C struct that hold the same information.

for error C2320 I have done the following say my function is Display_Image...then

typedef void (WINAPI *DLT_DisplayImage)(bool lUpdateCon, bool lForceDraw, int lSlice, double lInWinWid, double lInWinCen);
 and
class sappdll
{
//Construction
public
     
DLT_DisplayImage  Display_Image_dll;
}

is this right?

ice
0
 
BorlandManCommented:

That is declared right.

To keep things simple, I would try doing it in a C type routine before I go hog wild and stick it in a class.

here's some boilerplate code for calling a dll dynamically at run time.

I have also included the delph dll source too below it so you can see there are no smoke and mirrors.

---------------------

typedef int (CALLBACK* MY_DOMESSAGE_PROC)(LPTSTR);

void Make_DllCall()
{
     
    HINSTANCE hinstLib;
    MY_DOMESSAGE_PROC     doMessageProcPtr = NULL;
    BOOL fFreeResult;
    BOOL fRunTimeLinkSuccess = FALSE;

     
    // Get a handle to the DLL module.
    hinstLib = LoadLibrary("MyDll.dll");
 
    // If the handle is valid, try
    // to get the function address.
    if (hinstLib != NULL)
    {
     // this points to the function address;
        // note the name of the function is case sensitive
        doMessageProcPtr = (MY_DOMESSAGE_PROC)
              GetProcAddress(hinstLib, "DoMessage");
 

        // If the function address
        // is valid, call the function.
        if (fRunTimeLinkSuccess =
              (doMessageProcPtr != NULL))
     {
        LPTSTR lpszStr = "Test Delphi";

        // actually calling the function here
           int retVal = doMessageProcPtr (lpszStr);
        if (retVal)
           MessageBox (NULL, "Clicked Yes",
                          "Status", MB_OK);
        else
           MessageBox (NULL, "Clicked Nope",
                          "Status", MB_OK);
     }
       
        // Free the DLL module.
        fFreeResult = FreeLibrary(hinstLib);
    }
 
    if (! fRunTimeLinkSuccess)
        MessageBox(NULL,
               "message via alternative method",
                "Error", MB_OK);

}


//
// Delphi DLL
//     The passing of the record I'm missing something
//     on at this moment.
//

library MyDll;

uses
  SysUtils,
  Classes,
  Dialogs,
  controls;

{$R *.res}

type
  TMyRec = record
    Name: string;
    Value: boolean;
    Amount: Integer;
  end;

function DoMessage(szMessage:pchar):integer; stdcall;
var
   sMessage: string;
begin
  sMessage := szMessage;  // automatically converted
                          // from pchar to pascal string :)

  result := 0;
  if MessageDlg(sMessage, mtInformation,
               [mbyes, mbno], 0) = mrYes then
     result := 1
end; // DoMessage

//
// this is not right yet, sorry. I'm missing something
// here which isn't returning right.
//
function getMyRec ( ARec: TMyRec):integer; stdcall;
begin
  arec.Name := 'Hello World';
  arec.Value := false;
  arec.Amount := 42;
end;

exports
  DoMessage,
  getMyRec;
begin
end.
0
 
iceblue_22Author Commented:
J...ur a legend...

right now I have about 8 errors....I figured out the prob with bool...but wht is pissing me off right now is the followig error....
error C2320: expected ':' to follow access specifier 'type'
and
fatal error C1070: mismatched #if/#endif pair in file 'sapp.dll'

both of these I can't figure out. Also in relation to the delphi data types what I have done is written up C struct that hold the same information.

for error C2320 I have done the following say my function is Display_Image...then

typedef void (WINAPI *DLT_DisplayImage)(bool lUpdateCon, bool lForceDraw, int lSlice, double lInWinWid, double lInWinCen);
 and
class sappdll
{
//Construction
public
     
DLT_DisplayImage  Display_Image_dll;
}

is this right?

ice
0
 
iceblue_22Author Commented:
J.

its official....I am in love with you!!!!...

thanks sooo much....I just got a look at your code for delphi and VC++....actually I have made life a lil bit easier as I now only need to call A function....without any delphi data types......

as you have given me a working version of the dll I am going to follow it like the gosple truth!!!

ice....

PS: will defintely get back to you on my success.....(:
0
 
BorlandManCommented:

Display_Image_dll is a variable which points to the function, yes.

but now you need to do the GetProcAddress() stuff to get a pointer to the function in the dll.

looks good so far.

J
0
 
BorlandManCommented:

Thanks for the kind words   :)
(unix right?)

Good job making your dll calls use standard C data types, that should simplify things considerably.

looks like your pretty much there.

just out of curiosity what was this project for? .. and how did Delphi get involved with it?

alright then,
take it easy,
sincerely,
J
0
 
iceblue_22Author Commented:
Hiya J...

am doing all tht u've hinted towards...hopefully its all good.....this is wht my final thing looks like
sapp_dll::sapp_dll()
{
                HINSTANCE hinstLib;
          DLT_DisplayImage Display_Image_dll = NULL;
          BOOL fFreeResult;
          BOOL fRunTimeLinkSuccess = FALSE;

          //Get handle to the DLL module.
          hinstLib = LoadLibrary("sappdll.dll");

          //If the handle is valid try to get the function address.
          if(hinstLib != NULL)
          {
               //this points to the function address
               //note the name is case sensitive
               Display_Image_dll = (DLT_DisplayImage)GetProcAddress(hinstLib,"DisplayImage");
               
               //if function address is valid, call the function
               if(fRunTimeLinkSuccess = (Display_Image_dll != NULL))
                    (Display_Image_dll)("message via DLL function\n");

               //free the DLL module.

               fFreeResult = FreeLibrary(hinstLib);
          }

          //If unable to call the DLL function use an alternative.

          if(!(fRunTimeLinkSuccess))
               printf("message via alternative method\n");
}

I did go crazy and put it in a class...so according to what u've told me so far.....from here on I will just need to call the function and the dll will take over from there...rite?

ice
0
 
iceblue_22Author Commented:
now the mix of delphi and VC++....

I am been trying to debug a medical image viewer as part of my IT for my degree.....the problem was that the application(in VC++) couldn't read certain file formats......

So out I went and got some code which did this...the only problem was that it was in delphi.....so far I have had no exp with windows programming at all(yups I am a unix chic)...

...thus end my story......only thing left to say is THANK YOU!!!!

check you out later,
ice
0
 
iceblue_22Author Commented:
by the way J could I have put in the calling of the DLL in any class??

ice
0
 
iceblue_22Author Commented:
once again thank you....u've helped me get this thing done on time....

take care,
sincerely,
ice
0
 
BorlandManCommented:

Hi,
a medical image viewer very cool. I've done some software, which communicates with embedded devices, it's interesting and tricky stuff... what file format were you trying to read?... just out of curiosity (yep, I'm a Curious George)

by the way, Delphi is a very cool tool. It gives you the power of c++ and the rad of Visual Basic. You can sit at a high level of doing just component gui stuff and not have to muck with Windows APIs or you can dig down and do that too... excellent tool for database development and very object-oriented... good for developing apps in Windows even if you don't know Windows... then as you get more into it, Delphi helps you there too... if you want a c++ version of Delphi, check out c++ Builder at www.borland.com
... it supports all the same types and components as Delphi does... so if you were using C++ Builder, you could have simply linked in the code you had for delphi without having to use a dll....

as for putting the call to the dll in the class that is fine. I was just suggesting this to minimize the things that could go wrong.

oh quick observation, there is a printf() in the code I gave you, you might want to change that to
MessageBox (NULL, "the error message", "Title of dialog", MB_OK);

Unix is cool. I have always liked vi (my windows buddies think I am  sick)... and the way you can chain little programs together.. have you checked out Apples OS X ??
It is built on Unix BSD and Mach .. very slick.

anyway,
take it easy,
John Scalco
0
 
iceblue_22Author Commented:
dude I am nearly there....

except that after declaring the calling of the dll func in my sapp_dll class....I don't know how to call Display_image in other classes.....any ideas?

the image format I am working is called DICOM...its a industry standard for all medical images.....yep its been great leanrning abt the stuff....

and hence forth after the last month on windows i am definitely gonna try getting comfortable with it......

0
 
iceblue_22Author Commented:
hey dude,

ur MessageBox statement come up with the error..
error C2660: 'MessageBoxA' : function does not take 4 parameters

also i am trying to use Display_Image like so....
sapp_dll::Display_Image_dll(false, false, 0, 10, 0);
however I get 2 errors
'sapp_dll' : is not a class or namespace name //however sapp_dll is a class
'Display_Image_dll' : undeclared identifier //and I have defintely declared this like u told me to.....

waiting for a reply....
urs,
ice
0
 
BorlandManCommented:

MessageBox(NULL, "Message", "Title", MB_OK);

.. if your doing it from inside a class you have to
say ::MessageBox(NULL, "Message", "Title", MB_OK);
as the compiler thinks you are calling a method inside of the class

as for sapp_dll, my guess, based on previous discussions is that you have declared the class, maybe something like this:

class sappdll
{
//Construction
public
   
DLT_DisplayImage  Display_Image_dll;
}

Ok, well you can't say this

sapdll::Display_Image_dll(..);

unless you make the Display_Image_dll a static method.

what I think you want to do is create an instance of the class and then call the method - did you create your object?

ex:

void Test_Drive()
{
   sapdll*  pMySapDll;

   pMySapDll = new MySapDll();
   pMySapDll->Display_Image_dll(...);

   delete pMySapDll;

}

or you can create it on the stack frame

void Test_Drive2()
{
   sapdll MySapDll;

   MySapDll.Display_Image_dll(...);

}


hope that helps,
J
0
 
iceblue_22Author Commented:
hi J.....

sorry for the late reply...
I have been away for the past 2 days...and wont be at work till the coming tuesday...I don't have any of the stuff on me...so am taking a break frm it for a few days...remember me only a uni student...and it starts this monday......

hopefully u won'r be too buggered abt helping me out on tuesday when I get stuck....

ice
0
 
BorlandManCommented:
I thought you had it working now?

if you need help, post the question and I'll see what I can do.

J
0
 
iceblue_22Author Commented:
sure will.

later dude,
ice
0
 
iceblue_22Author Commented:
hey am back....

well I did everything that you suggested.....so far I have got the dll to compile without errors vut I don't know what I have done in calling it.....

the exe just crashes when I run the particular function.
This is the code I wrote in the class sappdll.cpp:

sapp_dll::sapp_dll()
{
          HINSTANCE hinstLib;
          DLT_DisplayImage Display_Image_dll = NULL;
          BOOL fFreeResult;
          BOOL fRunTimeLinkSuccess = FALSE;

          //Get handle to the DLL module.
          hinstLib = LoadLibrary("sappdll.dll");

          //If the handle is valid try to get the function address.
          if(hinstLib != NULL)
          {
               //this points to the function address
               //note the name is case sensitive
               Display_Image_dll = (DLT_DisplayImage)GetProcAddress(hinstLib,"DisplayImage");
               
               //if function address is valid, call the function
               /*if(fRunTimeLinkSuccess = (Display_Image_dll != NULL))
                    (Display_Image_dll)("message via DLL function\n");*/

               //free the DLL module.

               fFreeResult = FreeLibrary(hinstLib);
          }

          //If unable to call the DLL function use an alternative.

          if(!(fRunTimeLinkSuccess))
          ;     //MessageBox (NULL, "the error message", "Title of dialog", MB_OK);
}

and this is how I called the function in another class within the project:

DLT_DisplayImage Display_Image_dll = NULL;
Display_Image_dll(false, false, 0, 10, 0);

is this correct? My header is fine so I can't seem to find the problem...I put in the static parameters just to try the thing out first.

waiting for ur reply,
ice

0
 
iceblue_22Author Commented:
hey am back....

well I did everything that you suggested.....so far I have got the dll to compile without errors vut I don't know what I have done in calling it.....

the exe just crashes when I run the particular function.
This is the code I wrote in the class sappdll.cpp:

sapp_dll::sapp_dll()
{
          HINSTANCE hinstLib;
          DLT_DisplayImage Display_Image_dll = NULL;
          BOOL fFreeResult;
          BOOL fRunTimeLinkSuccess = FALSE;

          //Get handle to the DLL module.
          hinstLib = LoadLibrary("sappdll.dll");

          //If the handle is valid try to get the function address.
          if(hinstLib != NULL)
          {
               //this points to the function address
               //note the name is case sensitive
               Display_Image_dll = (DLT_DisplayImage)GetProcAddress(hinstLib,"DisplayImage");
               
               //if function address is valid, call the function
               /*if(fRunTimeLinkSuccess = (Display_Image_dll != NULL))
                    (Display_Image_dll)("message via DLL function\n");*/

               //free the DLL module.

               fFreeResult = FreeLibrary(hinstLib);
          }

          //If unable to call the DLL function use an alternative.

          if(!(fRunTimeLinkSuccess))
          ;     //MessageBox (NULL, "the error message", "Title of dialog", MB_OK);
}

and this is how I called the function in another class within the project:

DLT_DisplayImage Display_Image_dll = NULL;
Display_Image_dll(false, false, 0, 10, 0);

is this correct? My header is fine so I can't seem to find the problem...I put in the static parameters just to try the thing out first.

waiting for ur reply,
ice

0
 
BorlandManCommented:
Hi,
You aren't doing a check on the ptr to the function, so if it comes back incorrect or NULL, then you just call it anyway, at least that's what it looks like


you should probably add a check like this (which i included in the sample <wink-wink>


Display_Image_dll = (DLT_DisplayImage)GetProcAddress
                            (hinstLib,"DisplayImage");

// check GetProcAddress returned correct address
// if you access it and the address is wrong your hosed!
//
if (Display_Image_dll != NULL) {
   /* do your thing here */
}
else {
   MessageBox (NULL, "Could not find address of fn",
               "Status Dialog", MB_OK);
}


Please provide your declaration for DLT_DisplayImage
(the pointer to the function declaration)

and the prototype of the function you are calling in the Delphi dll.

I'd like to look at those see if anything is amiss.


hth
J
             

0
 
iceblue_22Author Commented:
hi,

DLT_DisplayImage looks like so in the header:
typedef void (WINAPI *DLT_DisplayImage)(BOOL lUpdateCon, BOOL lForceDraw, INT lSlice, double lInWinWid, double lInWinCen);
and in delphi looks like this:
  procedure DisplayImage(lUpdateCon,lForceDraw: boolean;lSlice: integer; lInWinWid,lInWinCen: double); stdcall;

is there a problem in the translation?

regards
Sri
0
 
iceblue_22Author Commented:
hey I just have a query...

the change you wanted me to make can be done in my sappdll.cpp file rite?

and then I proceed to call the function in another class like I said above:

DLT_DisplayImage Display_Image_dll = NULL;
Display_Image_dll(false, false, 0, 10, 0);

correct?
0
 
iceblue_22Author Commented:
hey I just have a query...

the change you wanted me to make can be done in my sappdll.cpp file rite?

and then I proceed to call the function in another class like I said above:

DLT_DisplayImage Display_Image_dll = NULL;
Display_Image_dll(false, false, 0, 10, 0);

correct?
0
 
BorlandManCommented:
Ok,

Short answer, the changes I suggested should be in the application which is calling the dll (your c++ application)

Your problem is most likely that you are not checking for null when you call GetProcAddress() - you should make it a habit to do this. Because if the function is not found in your dll, then you will be trying to call a NULL pointer.

So, test for that. If you are getting NULL, then it means that (a) you are not loading the right dll (do you have a copy in more than one place (ex: C:\mydev and c:\WinNt\System32) - you might think your calling one dll, when in fact your calling an old dll.

If you are sure you are calling the right dll (that is, there is only one of these dlls on your computer), then check that you have your exports in the Delphi dll.


Next, another point to consider (not necessarily the cause of your bug), but... if any of the params you are passing in to your dll, you expect to return a value from the dll; Say, lUpdateCon is used to determine from the dll the update status, then you need to make a change, because  BOOL lUpdateCon passes in a copy, not a pointer of the variable, so any changes made in the dll to the variable you passed in will never be returned back to your program.
You need to pass the address of your variable in your application into the dll - pointers.

Here's an example. For this example, let me assume that you expect all params to change in the dll and want to get that in your main application when the dll is done being called.

The changes you would make would be something like this:

typedef void (WINAPI *DLT_DisplayImage)(BOOL* lUpdateCon,
               BOOL* lForceDraw,
               int* lSlice,
               double* lInWinWid,
               double* lInWinCen);

your delphi procedure would look almost the same, but you put var in front of each variable which you want to pass back and forth from the dll

ex:

procedure DisplayImage(var lUpdateCon: boolean;
                       var lForceDraw: boolean;
                       var lSlice: integer;
                       var lInWinWid: double;
                       var lInWinCen: double); stdcall;

Note: if you use var, then you must separate each variable's declaration with a semicolon.

You can't say this:  var lUpdateCon, var lForceDraw: boolean


Here's an example of calling it from a dll.


hinstLib = LoadLibrary("MyDll.dll");
 
if (hinstLib != NULL) {

  doItProcPtr = (DLT_DisplayImage) GetProcAddress
                         (hinstLib, "DisplayImage");

  if (fRunTimeLinkSuccess = (doItProcPtr != NULL))
  {
    BOOL lUpdateCon = false;
    BOOL lForceDraw = false;
    int lSlice = 0;
    double lInWinWid = 0;
    double lCen = 0;

    // passing the address of the variables here
    // so we'll know the changes.
    doItProcPtr (&lUpdateCon, &lForceDraw,
                 &lSlice, &lInWinWid, &lCen);
  }
  // Free the DLL module.
 
  fFreeResult = FreeLibrary(hinstLib);


ok?

This should fly, if you still have errors.
comment out your dll's code in teh function and put one line in there:  MessageBox (NULL, "Can you hear me now?",
                           "Test Dialog", MB_OK);

run your app, the message should appear, if it does not, you still don't have your dll setup correctly - if it does display the message, then all is well with your dll functions - it's something in your code that is causing the crash.


hope that helps,
I'm not sure what time zone your in, but I'm headin' for bed, I'll check mail in the morning.

hth,
J
0
 
iceblue_22Author Commented:
hey I just have a query...

the change you wanted me to make can be done in my sappdll.cpp file rite?

and then I proceed to call the function in another class like I said above:

DLT_DisplayImage Display_Image_dll = NULL;
Display_Image_dll(false, false, 0, 10, 0);

correct?
0
 
iceblue_22Author Commented:
hey borlandman,

how do I use doubles in my parameters? using these gives as u suggested gives me the following error:

'void (bool,bool,int,double,double)' : cannot convert parameter 5 from 'double *' to 'double'

wht do you reckon I need to use...is there something like LPTSTR?

thanks dude
Sri
0
 
SalteCommented:
The best way to figure out what to name the function in argument to GetProcAddr is to inspect the DLL with some form of DLL viewing tool and see what the DLL think the name is. It isn's always the same as what C++ think it is. I assume you have already specified extern "C" so it is actually what you might think C think it is.


The point is that the C compiler (and the C++ compiler when using extern "C") also do some name mangling, it isn't as fancy as for C++ but there is some.

First, stdcall and cdecl uses different name mangling, stdcall typically looks like:

Foo@28

This is a function foo with an argument list so large that the size of it is 28 bytes.

Not sure if you can simply place "DisplayImage" as the name of the function to GetProcAddr, I would think you would have to write something like:

DisplayImage@N where N is some number and typically a multiple of 4 since an argument list is usually or always a multiple of 4 bytes.

Secondly, as far as I know, C++ does know about the bool type. I even thought that C knows about the bool type since the C99 version, I may be wrong in this though.

The typedef BOOL that windows uses isn't bool however, it is defined as:

typedef int BOOL;

so it really is the same as int. This is because it stems from the days when C didn't have bool type and there was no C++.

Alf
0
 
iceblue_22Author Commented:
Alf,

my error is more to do with the double....when i put in a double the compilers complains tht the conversion frm double * to double can't be made...but doesn't have this problem with int or bool....I thk bool...isn't so bad as WINAPI will realize tht the BOOL is the same as bool rite??

thanks,
ice
0
 
BorlandManCommented:

Hi IceBlue_22,

did you check that you are only have one of these dlls on your system? Do a search and double check. You can have the same dll on your machine in different folders many times, but Windows will use the one first found in your WinNt\System32 folder and then look in you applications folder..... so one dll could hide the other.... Make sure!! Otherwise you may be on a wild goose chase and it may infact work.


regarding your question about the double, that should be fine. I guess I didn't explain this very well in my last posting (above), but if you want to pass in a parameter and have that parameter change, then you need to pass a pointer.

say you have a function called

Random_Num()

you pass in an integer and that integer will be changed by the function, for this to happen you pass an address

int myNum = 0;
Random_Num (&myNum);

// now it's maybe 42 or some random number.
after the call myNum will be populated with whatever Random_Num() wrote into that variable.


in your dll (delphi one) you need to change your function to look like this:

procedure DisplayImage(var lUpdateCon: boolean;
                      var lForceDraw: boolean;
                      var lSlice: integer;
                      var lInWinWid: double;
                      var lInWinCen: double); stdcall;

see the 'var' in front of each variable, that means that when you call this procedure from see, you must pass the address. So, you put var in front of whatever variable you want to be able to return. You don't have to put it on all of them, just the ones that you want to get the value.

var is Delphi's way of saying that this variable can be changed by the function and returned back to the caller.


Your typedef should look like this:

typedef void (WINAPI *DLT_DisplayImage)(BOOL* lUpdateCon,
              BOOL* lForceDraw,
              int* lSlice,
              double* lInWinWid,
              double* lInWinCen);

basically put a *  whereever you have a parameter you want to get back with a result which was set in the dll.

from your c++ application's function where you call
say your function where you call this is DisplayStuff(),
you should call LoadLib() - like we have in the past discussions, check the pointer is ok, then use GetProcAddress() to get a pointer to the function, check that the pointer is not NULL and then make the call below

doItProcPtr (&lUpdateCon, &lForceDraw,
             &lSlice, &lInWinWid, &lCen);

and that should work.

if you still can't get this to work, then I suggest you

1. Include in your next mail the declaration of your procedure in the DLL (delphi)

2. Your current typedef which you use to call that procedure.

ok?
J

0
 
SalteCommented:
Err...

The type 'double *' is a pointer to double.

'int *' is a pointer to an int

and 'bool *' is a pointer to a bool.

All these are different from double, int and bool.

If you have a double * and you want a double you need to dereference the pointer:

double x;
double * px = & x;

px is now pointing to the x.

*px = 1.0; // set x to 1.0

func(*px); // give the value 1.0 as argument to function func.

Func is here a function that takes a double as argument.

Use & x to get from type T to type 'T *'. If x is of type T then & x is of type 'T *' and has a value that is a pointer to the variable x.

Use *px to get form type 'T *' to type T. If px is of type 'T *' then *px is of type T and is the contents of the variable which px is pointing to.

If px points to x and x has the value 3.14 then *px will evaluate to the value 3.14 and if assigned to as in:

*px = 2.7;

Then it is the variable x that is assigned to. If you instead do:

double y;
px = & y;

Then it is not x that is changed but the pointer px is now changed to point to y instead of x from then on *px = 1.2; will set y to 1.2 and x will not be touched.

double *px;

is very different from

double x;

It is two different types, the latter is a value of type double (floating point) and the former is a value that can hold the location of a double variable. Actually, it doesn't have to be a variable, it can also be an element of an array:

double arr[5];
double * px = & arr[3];

In this case px holds the address of element arr[3] so *px will reference the value in that array element. When used as pointer to array element you can also do pointer arithmetic:

px + 1   will be a pointer to arr[4] so

*(px + 1) = 3.7;

will change arr[4] to 3.7

In fact: arr[4] is exactly the same as *(arr + 4) where the array arr is used as a pointer to the first element. This is why you often see functions that take a pointer type such as buffer or table or array. The pointer received is simply the pointer to the first element of that array or table and if you then also have a count of how many elements the array or table contains you can reach all the elements from that pointer.

double arr[10];

func(arr,10);

func might have a prototype like:

void func(double * vec, int count)
{
   ....
}

The array is transferred but the function doesn't see the array, it see a pointer to the first element of the array.
*vec is the same as arr[0], *(vec + 1) is the same as arr[1] etc... you can also write vec[0] and vec[1] etc, they mean the same thing: vec[x] is the same as *(vec + x).

I don't think you can resolve your problem by sending the double as a group of 2 32 bit ints. Your problem is rather that you have a pointer to double and try to send that as the double itself. Use *pdbl as argument instead of pdbl.

Alf
0
 
SalteCommented:
err disregard part of my previous post, I got the question mixed up with another question and part of my response was a response to the a question that wasn't the question here :-)

Anyway, the fact that pointer to double and double are two different types still remain. Disregard the thing about transferring two 32 bit values instead of double and other non-sense :-) That doesn't belong here.

Alf
0
 
BorlandManCommented:

Right pointer to double and a double are different.
Alf, you might want to read the previous posts to get an idea what is going on.

It looks like IceBlue is not calling her dll correctly.
I say this because I have compiled similar code, code which calls a Delphi dll from a visual c++ application - that is what she is trying to do... and Delphi does handle double with no problems. So, I think it's just a little error somewhere.

hth,
J
0
 
iceblue_22Author Commented:
Hi J,

I am taking a day off work today and will be back on the case tomorrow. will defintely try to make the changes tht u suggested. I think my problem is on the delphi end of the question as I didn't do precisely what u have said above. I am pretty confindent on the VC++ side as I did wht told me ealier.

btw dude all ur seggestions have been very very helpful, thanks once again for them(I knw I am repeating myself.....(:)

I am from sydney australia....not quite sure abt the time zone.

cheers,
sri
0
 
SalteCommented:
I did read the backlog previously, so I sort of knew what was going on, I just mixed this thread with another thread and goofed :-) There's another thread where a guy is trying to pass a VB double to a C++ function and for some reason he cannot or will not use 'double' but want to use two 32 bit integers or some such instead. So I started to respond to his thread in this thread. Plain goof in other words :-)

In any case pointer to double and double are still different types.

What is the prototype in Delphi and what is the C/C++ prototype you're using?

Those two has to match somehow...

procedure foo;

void foo();

function bar return integer;

int bar();

etc etc...
function baz(x:Double) return double;

double bar(double x);

the argument name doesn't have to match but the types must and when you call the function you must call it with values matching the argument list, so a double require a type of double and not a pointer to double.

Be very wary when Delphi uses 'var' or reference parameters:

procedure DisplayImage(var lUpdateCon: boolean;
                     var lForceDraw: boolean;
                     var lSlice: integer;
                     var lInWinWid: double;
                     var lInWinCen: double); stdcall;

In C++ and C you can write this like:

void __stdcall DisplayImage(bool * UpdateCon,
                            bool * lForceDraw,
                            int * lSlice,
                            double * lInWinWid,
                            double * lInWinCen);

For C pre C99 you must also have a:

typedef int bool;

you should probably also use 'int' of appropriate size instead of the bool if Delphi's bool has different size than C++'s bool type. Check delphi's bool and see how many bits it is, and if that fit with sizeof(bool) then it's fine, otherwise use int/short/char depending on the size of delphi bool. If delphi's bool is 1 byte then most likely you should use char instead of bool for delphi's bool.

Also, note that since the var arguments are really pointers, you must pass pointer values to them:

double x, y;
int k;
bool b, b2;

DisplayImage(&b,&b2,&k,&x,&y);

In delphi's var arguments they can either be both IN OUT or just OUT parameters, I think the 'var' keyword specify that they are both IN OUT while 'out' is what you would use for OUT arguments.

This means that all the variables b, b2, k, x and y must have reasonable values before calling the function. The function may modify those values.

If the parameters are for output only and the procedure ignore their initial values you don't have to put any special value in them.

When calling the function you MUST provide addresses, since the reference parameters translates to pointers in C and C++. Use the & as 'address of' operator as I showed above.

Alf
0
 
iceblue_22Author Commented:
Hi Alf,

thanks for ur suggestions.....will be in tomorrow so am defintely gonna implement the above changes that both u and J have given.

later,
ice
0
 
BorlandManCommented:

Hi IceBlue_22,
How are you?

hope you have a good day off.

please post your declaration for the procedure on the Delphi side and we'll straighten it out.

also, if you could indicate what parameters you want changed by the dll, i'm sure that would be useful.

worse comes to worse, i have some skeleton (c++ and delphi) code I slapped together which matches your function declarations - with doubles being used and it works fine.... tha'ts why i asked if your blow up was because (a) your checking the ptr to the function (b) your calling the function and it blows up or (c) your calling it and something IN the function is blowing up.

talk to you when you come back,
have a good one.

i heard it's going to be warm in Sydney today <grin>
hmmm, time zone, yeh, I would imagine it's a bit different (heh heh) from where I am. I'm in the United States, SouthEast.

regards,
J
0
 
iceblue_22Author Commented:
Hi J....

actually its quite nippy here right now.....I ain't actually at work today have uni till tuesday....but yeah...

on the delphi side of things my declaration lookd like so:

procedure DisplayImage(var lUpdateCon: boolean;
                                 var lForceDraw: boolean;
                                 var lSlice: integer;
                                 var lInWinWid: double;
                                 var lInWinCen: double);                           stdcall;

very much like wht u have above......also i put in the exports clause only in the dll proj file in delphi....ie:
exports:
Display_image;

does this sound abt right to you?
MSDev right now doesn;t like me using a double for the function as I have it declared as a double *.......

wht do you thk??.....I will be back at my workplace on tuesday....

see you then...
later ice...

its winter or autum for u rite now yeah??...have a good one....LOL
0
 
BorlandManCommented:

hi,
oh, I guess I have been fooled by the media. TV/Movies always show Australia (Sydney) warm... but obviously, it's seasonal..

the delphi declaration looks just right.

the exports though, I hope is a typo because the name of the function does not match that Display_image != DisplayImage

so that could be an issue.

To make certain that it is not and you are exporting your function from the delphi dll correctly, go to your Visual Studio folder and pick the sub folder in there called "Visual Studio tools", in that folder is a program called depends. Start it. Pick from the file menu, Open. A common dialog to select a file should appear. Navigate to the location where your dll is. Click on the dll and click 'open' button (or dbleclick file item). The result should be that a window appears with a treeview pane on the left. It shows you the dll and all dlls that your dll uses (surprise!).. to the right of that pane (like window pane), you should see 3 other windows the one in the middle lists your exported functions - if there are no items in that window, then you have not exported your function correctly. If it is in there, then you've done it right.


as far as the function on the visual c++ side goes, yes, you should be using double*

and call the function like so:  DoIt( &mydblVar )
making sure you are passing a pointer to the double - so that your dll can change the data you pass it from your application.


as for where I am it was 74 degrees today, but we have been having ups and downs. 2 weeks ago we had a couple of inches of ice....(which is unusual) There are some days I wear short sleeves and others I wear my sailor jacket...
Time zone, looks like it's 12:47 your time (March 6) and 9:00pm my time (March the 5th)... so i guess your a few hours ahead.

oh well, talk to you later,
sincerely,
J


0
 
SalteCommented:
How does the declaration looks like on the C++ side?

I would assume that

var foo: Double

would translate to

double * foo

in the argument list. However, that also means that the caller must call it as a pointer:

double x;

DisplayImage( ...,&x,...);

If you try:

DisplayImage(.....,x,....);

you will get error on the MSDEV side.

I am also uncertain about the boolean data types, if they are compatible or not. Is sizeof(bool) in C++ side the same as the size of Boolean on the Delphi side?

Alf
0
 
iceblue_22Author Commented:
Hi J,

please stick around as i am sure to get back to u on how wht u'll asked me to do went......this is gonna be tuesday....is there a way I can send the query directly to you?

actually I am getting a cold right now...very bad for my singing...but yeah...

later,
ice
0
 
BorlandManCommented:
Alf

good suggestion about using the double* - just what I suggested too.

as for bool, boolean works on the delphi side.

IceBlue_22 -
I'm in meetings today, but 'listening'.. this has been going on quite a long thread if I do say so myself.

if you want to send me an email is that what you mean by a query, search the web (google) for a Company called "Ideal Software Inc.", there should be an email link there... I don't provide it here because of spammers. ok? ... also I mentioned my name in the post where I was talking about unix and the mac.

oh singer eh?  I play guitar and a few other things, so I don't have to worry about the colds (heh heh)

As my mom always says "Drink plenty of liquids and rest"
free advice.

sincerely,
J
0
 
iceblue_22Author Commented:
Hi J,

yups this has been going for quite a while...and I throughly sympathize with you abt putting up with me.....but I do belive that once I put in the changes that both urself and Alf have given me.....it'll all be good....plz let it be!!!

Guitar??...how long have u been playing tht??....I have been singing for the past 14yrs....its all good.....plenty of liquids is all good but rest ain't possible by me.....

have a good wkend......later..

ice
0
 
BorlandManCommented:
Is it already the weekend? geeze...

Glad to help out if I can and I can get the time to... and the person is appreciative... so far all conditions are being met, so no problem.. but thanks for being appreciative, I appreciate you being appreciative .... heh heh like "Help me to help you" [Jerry Maguire] ....

Guitar oh how's about 22ish years. I've been writing songs about the same time too... yep that's the "other side of me" a musical creative type... one of these days I'll put up some mp3s of some tunes I've written and performed..

have a good weekend and if you want to write me directly, look me up.

J
0
 
iceblue_22Author Commented:
hi J...

wow thts cool...never been confindent enough to write my own songs...send us some of the mp3's when they're done....maybe I should try now.....

but hope u have a good weekend.....btw can't find anything on ur company(will try again)....

later...probably tuesday...
ice
0
 
iceblue_22Author Commented:
HI J,

well it compiles...but crashes when I use then funstion to open my image.....I don't understand where the problem stems from.

this is how I am calling the function:
{
/*DLT_DisplayImage Display_Image_dll = NULL;
                    Display_Image_dll(false, false, 0, 10, 0);*/

                    HINSTANCE hinstLib;
                    DLT_DisplayImage Display_Image_dll = NULL;
                    BOOL fFreeResult;
                    BOOL fRunTimeLinkSuccess = FALSE;

                    //Get handle to the DLL module.
                    hinstLib = LoadLibrary("sappdll.dll");

                    //If the handle is valid try to get the function address.
                    if(hinstLib != NULL)
                    {
                         //this points to the function address
                         //note the name is case sensitive
                         Display_Image_dll = (DLT_DisplayImage)GetProcAddress(hinstLib,"DisplayImage");
               
                         //if function address is valid, call the function
                         if(fRunTimeLinkSuccess = (Display_Image_dll != NULL))
                         {
                              BOOL lUpdateCon = false;
                              BOOL lForceDraw = false;
                              int lSlice = 0;
                              double lInWinWid = 10;
                              double lInWinCen = 0;

                             
                              BOOL* plUpdateCon = &lUpdateCon;
                              BOOL* plForceDraw = &lForceDraw;
                              int* plSlice = &lSlice;
                              double* plInWinWid = &lInWinWid;
                              double* plInWinCen = &lInWinCen;

                              Display_Image_dll(*plUpdateCon, *plForceDraw, *plSlice, *plInWinWid, *plInWinCen);

                         }
                         //free the DLL module.

                         fFreeResult = FreeLibrary(hinstLib);
                    }
the typedef is as follows:

typedef void (WINAPI *DLT_DisplayImage)(BOOL* lUpdateCon,
             BOOL* lForceDraw,
             int* lSlice,
             double* lInWinWid,
             double* lInWinCen);
and the delphi declaration is:

procedure DisplayImage(var lUpdateCon: boolean; var lForceDraw: boolean; var lSlice: integer; var lInWinWid :double; var lInWinCen: double); stdcall;

I have done exactly as you have advised......know I am unsure about whether the problem is with the program or the files themselves.

I knw this is probably not something you can help me with as u don't have acess to all my code. However if you see something in what I have done tht could perpetrate the problem please let me know.

thanks....btw everything you have said so far has helped...
Ice
0
 
iceblue_22Author Commented:
HI J,

well it compiles...but crashes when I use then funstion to open my image.....I don't understand where the problem stems from.

this is how I am calling the function:
{
/*DLT_DisplayImage Display_Image_dll = NULL;
                    Display_Image_dll(false, false, 0, 10, 0);*/

                    HINSTANCE hinstLib;
                    DLT_DisplayImage Display_Image_dll = NULL;
                    BOOL fFreeResult;
                    BOOL fRunTimeLinkSuccess = FALSE;

                    //Get handle to the DLL module.
                    hinstLib = LoadLibrary("sappdll.dll");

                    //If the handle is valid try to get the function address.
                    if(hinstLib != NULL)
                    {
                         //this points to the function address
                         //note the name is case sensitive
                         Display_Image_dll = (DLT_DisplayImage)GetProcAddress(hinstLib,"DisplayImage");
               
                         //if function address is valid, call the function
                         if(fRunTimeLinkSuccess = (Display_Image_dll != NULL))
                         {
                              BOOL lUpdateCon = false;
                              BOOL lForceDraw = false;
                              int lSlice = 0;
                              double lInWinWid = 10;
                              double lInWinCen = 0;

                             
                              BOOL* plUpdateCon = &lUpdateCon;
                              BOOL* plForceDraw = &lForceDraw;
                              int* plSlice = &lSlice;
                              double* plInWinWid = &lInWinWid;
                              double* plInWinCen = &lInWinCen;

                              Display_Image_dll(*plUpdateCon, *plForceDraw, *plSlice, *plInWinWid, *plInWinCen);

                         }
                         //free the DLL module.

                         fFreeResult = FreeLibrary(hinstLib);
                    }
the typedef is as follows:

typedef void (WINAPI *DLT_DisplayImage)(BOOL* lUpdateCon,
             BOOL* lForceDraw,
             int* lSlice,
             double* lInWinWid,
             double* lInWinCen);
and the delphi declaration is:

procedure DisplayImage(var lUpdateCon: boolean; var lForceDraw: boolean; var lSlice: integer; var lInWinWid :double; var lInWinCen: double); stdcall;

I have done exactly as you have advised......know I am unsure about whether the problem is with the program or the files themselves.

I knw this is probably not something you can help me with as u don't have acess to all my code. However if you see something in what I have done tht could perpetrate the problem please let me know.

thanks....btw everything you have said so far has helped...
Ice
0
 
iceblue_22Author Commented:
HI J,

well it compiles...but crashes when I use then funstion to open my image.....I don't understand where the problem stems from.

this is how I am calling the function:
{
/*DLT_DisplayImage Display_Image_dll = NULL;
                    Display_Image_dll(false, false, 0, 10, 0);*/

                    HINSTANCE hinstLib;
                    DLT_DisplayImage Display_Image_dll = NULL;
                    BOOL fFreeResult;
                    BOOL fRunTimeLinkSuccess = FALSE;

                    //Get handle to the DLL module.
                    hinstLib = LoadLibrary("sappdll.dll");

                    //If the handle is valid try to get the function address.
                    if(hinstLib != NULL)
                    {
                         //this points to the function address
                         //note the name is case sensitive
                         Display_Image_dll = (DLT_DisplayImage)GetProcAddress(hinstLib,"DisplayImage");
               
                         //if function address is valid, call the function
                         if(fRunTimeLinkSuccess = (Display_Image_dll != NULL))
                         {
                              BOOL lUpdateCon = false;
                              BOOL lForceDraw = false;
                              int lSlice = 0;
                              double lInWinWid = 10;
                              double lInWinCen = 0;

                             
                              BOOL* plUpdateCon = &lUpdateCon;
                              BOOL* plForceDraw = &lForceDraw;
                              int* plSlice = &lSlice;
                              double* plInWinWid = &lInWinWid;
                              double* plInWinCen = &lInWinCen;

                              Display_Image_dll(*plUpdateCon, *plForceDraw, *plSlice, *plInWinWid, *plInWinCen);

                         }
                         //free the DLL module.

                         fFreeResult = FreeLibrary(hinstLib);
                    }
the typedef is as follows:

typedef void (WINAPI *DLT_DisplayImage)(BOOL* lUpdateCon,
             BOOL* lForceDraw,
             int* lSlice,
             double* lInWinWid,
             double* lInWinCen);
and the delphi declaration is:

procedure DisplayImage(var lUpdateCon: boolean; var lForceDraw: boolean; var lSlice: integer; var lInWinWid :double; var lInWinCen: double); stdcall;

I have done exactly as you have advised......know I am unsure about whether the problem is with the program or the files themselves.

I knw this is probably not something you can help me with as u don't have acess to all my code. However if you see something in what I have done tht could perpetrate the problem please let me know.

thanks....btw everything you have said so far has helped...
Ice
0
 
BorlandManCommented:
this line shouldn't be this:

Display_Image_dll(*plUpdateCon, *plForceDraw, *plSlice, *plInWinWid, *plInWinCen);


Do you want to pass in to the function the number which you are pointing to or the address of the variable which you are pointing to?

I think you want to allow the function to change the value in the variable, so it's probably the address of the variable you want to pass in. It should be this:

Display_Image_dll(plUpdateCon, plForceDraw, plSlice, plInWinWid, plInWinCen);


Let's talk about this a minute:

Suppose you have a pointer to an int.

int* pi = NULL;   // init to null
int num = 42;

// to point to that number you do as you did above
pi = &num;  

pi now points to the address where the variable num is located in memory.

so, if you say this:

*pi    // says "get me the data the pointer is pointing at, in this case it's 42

pi     // says "get me the address of the variable
       // in memory (which contains 42)

So, how does your function compile and work (well ok, it blows up)...

since you are dealing with numbers

Display_Image_dll(*plUpdateCon, *plForceDraw, *plSlice, *plInWinWid, *plInWinCen);

this probably compiles and works - because C/C++ thinks "Hey ice is passing in some addresses to me (addresses can be long vars), so I'll try to process that"

but what you are passing into the dll is the numbers that the pointers are pointing to NOT the address of the variables which the pointers point to.

I hope that makes sense and in no way is it meant to sound obnoxious, It isn't meant to, I'm just trying to explain it with an example so that it is clear (maybe easy to understand?) ... I mean 'easier' to understand, I don't think anyone should say this stuff is easy...


Hope that helps.
J
0
 
iceblue_22Author Commented:
HI J,

nopes I take no offence in you stating things as easy to understand as possible...only hope this isn't driving you crazy.

if there is no need for the * infront of my inputs while calling the function, I can just do wht u said earlier and wht I was doing myself. The problem is when I don't have this is just comes back with an error saying you can't pass a double* as a double and a int* as an int. In an errot to tackle this I changed the code to make sure only ints/doubles were passed into the dll func.

So when I change it to this:
Display_Image_dll(plUpdateCon, plForceDraw, plSlice, plInWinWid, plInWinCen);

then I get the following error:
error C2664: 'void (bool,bool,int,double,double)' : cannot convert parameter 5 from 'double *' to 'double'
        There is no context in which this conversion is possible

wht could the problem be?

Also I knw I asked earlier but my method of registering the dll in correct rite? using the LoadLibrary and Getprocaddress..??

thanks dude,
Ice
0
 
BorlandManCommented:
ok,

by the way, instead of doing this:


BOOL* plUpdateCon = &lUpdateCon;
BOOL* plForceDraw = &lForceDraw;
int* plSlice = &lSlice;
double* plInWinWid = &lInWinWid;
double* plInWinCen = &lInWinCen;

Display_Image_dll(*plUpdateCon, *plForceDraw,
   *plSlice, *plInWinWid, *plInWinCen);

you can do this if you want:

Display_Image_dll(&lUpdateCon, &lForceDraw,
                 &lSlice, &lInWinWid, &linWinCen);

onward.

you mechanism for calling it is correct, you do a LoadLib(),  you check that the pointer returned is ok, you then do a GetProcAddress() and you check that the pointer is non null before daring to use it <g>


on the double bit, your error says:

error C2664: 'void (bool,bool,int,double,double)' : cannot convert parameter 5 from 'double *' to 'double'
       There is no context in which this conversion is possible

Notice it says "convert parameter 5 from 'double *' to double' .... but isn't param 4 also a double?? How come it doesn't complain about that conversion?

I will send you a sample via email, watch for it.

hth,
J




0
 
SalteCommented:
I noticed that the typedef didn't have __stdcall while the Delphi had it.

_stdcall is not the default for C so you must specify it if you want it. Try

typedef void __stdcall (WINAPI *DLT_DisplayImage)(BOOL* lUpdateCon,
            BOOL* lForceDraw,
            int* lSlice,
            double* lInWinWid,
            double* lInWinCen);

I believe that is more comparable to the Delphi declaration.

Alf
0
 
iceblue_22Author Commented:
Hi alf...

is tht so?....I didnt realize......will make the change.

Hi J...

The error is repeated for both doubles and also for the int param.

I did get the stuff thanks(via email)......but I might not be able to have a look at it for a while as I earlier thought.....I just ain't cut out for full time uni and part-time work!!!!....

anyways I will try to defintely look at it before tuesday.....and of course let you knw....

take care...and hope there is a benevolent soul looking out for you as well...

ice
0

Featured Post

Industry Leaders: 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!

  • 41
  • 23
  • 8
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now