Solved

DLL call doesn't work

Posted on 2004-08-09
9
235 Views
Last Modified: 2010-04-05
Hi all,

I have a problem with a call to a DLL apparently written in C.
(It's Fastlook 11 if anyone knows it and has experienced similar problems)

The DLL is initialized correctly and other functions all work as expected.
It's just the function below that doesn't work.


In the help file there is the function prototype written as:

BOOL FAR PASCAL GetDwgName(int Channel, char FAR * DwgName)


So I wrote the following code to call this function:

===========================================
type
   TGetDwgName = function( Channel: Longint; FileName: PChar ): Longint; pascal;

var
   fnFileName  : TGetDwgName;


------------------------------------------
in some init func:


      @fnFileName := GetProcAddress( m_uiLibHandle, 'GetDwgName' );


-------------------------------------------
some other func:

var
   A: array[0..MAX_PATH] of Char;
begin
   if( m_uiLibHandle <> 0 ) then
   begin
      fnFileName( ci_Channel, A );
      ViewFile( A, true );
   end;
end;


There is no error when the function is called, but it doesn't change anything
in the array! A has the same content as before.

I don't think that it is a problem in the DLL. I guess I have an error in my code
but I just can't find it. Any suggestions?

regards
Wyverex


0
Comment
Question by:Wyverex
  • 4
  • 3
  • 2
9 Comments
 
LVL 12

Expert Comment

by:Ivanov_G
Comment Utility
As I can see the function's result is BOOL, you declare it as LongInt... But frankly ... I don't think this is a problem...
0
 
LVL 12

Expert Comment

by:Ivanov_G
Comment Utility
BTW, what happens after this line:

@fnFileName := GetProcAddress( m_uiLibHandle, 'GetDwgName' );

what is the address of fnFileName???
0
 
LVL 17

Accepted Solution

by:
Wim ten Brink earned 250 total points
Comment Utility
Try
  type TGetDwgName = function( Channel: Longint; FileName: PChar ): Longint; cdecl;
Instead. Or play with the other calling conventions. (Register, Safecall, etc.)

But that should not be the real problem. What does suprise me in the C declaration is the use of FAR. AFAIK, in Windows 32 there are no NEAR or FAR pointers anymore. It seems you're looking at a 16-bits definition of the DLL. Is it a 16-bits DLL?

Do you also check if GetProcAddress assigns a value? If GetProcAddress cannot find a procedure, it doesn't raise an exception. It just returns nil. But then you'd tget an access violation...

Btw... Try calling it as: fnFileName( ci_Channel, @A );
Thus, you pass along the pointer to A, not A itself. It could be that Delphi is a bit confused about this and passes the wrong thing...
0
 

Author Comment

by:Wyverex
Comment Utility
Thx for the fast answers :-)

fnFileName contains a valid function address after the call to GetProcAddress.
So the function is indeed called.

Workshop_Alex wrote:
>> Btw... Try calling it as: fnFileName( ci_Channel, @A );
>> Thus, you pass along the pointer to A, not A itself. It could be that Delphi is a bit confused about this and passes the
>> wrong thing...

Tried that before. Doesn't work either the content is still unchanged.

>> What does suprise me in the C declaration is the use of FAR. AFAIK, in Windows 32 there are no NEAR or FAR
>> pointers anymore. It seems you're looking at a 16-bits definition of the DLL. Is it a 16-bits DLL?

I don't think so. I guess it is just a remnant, if anyone still uses 16-Bit windows and wants to use Fastlook.
As I said before I don't have any problems with other function calls in the same DLL. Even where there
is a string as a parameter.
But there was no other function yet that returns a string instead of just taking it. So I guess it has
something to do with a call-by-reference that goes wrong here.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
Okay, I think the definition should be:
  TGetDwgName = function( Channel: Longint; var FileName: PChar ): WordBool; pascal;

Tried that already?
0
 

Author Comment

by:Wyverex
Comment Utility
I tried that and there is a compiler error in the function call.
After adding the "var" to the parameter list you can no longer pass
an array of char into the function.

But I don't know what other data type I should use than
A: array[0..MAX_PATH] of Char


0
 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
Use this:

A: Array[0..MAX_PATH] of Char;
PA: PChar;
begin
  PA := @A;
  fnFileName( ci_Channel, PA );

It is likely though that fnFileName will return a new string instead of overwriting the old value. Perhaps fnFileName just wants a pointer to a char array and fills it with a new pointer. Anyway, Check after the call if (PA=@A) to see if I'm right or not. If I'm right, the fnFileName function might be allocating the memory for the string by itself... (Which might or might not cause a memory leak somewhere...)
0
 

Author Comment

by:Wyverex
Comment Utility
That didn't work either.

But I have found the problem now...
I had to use stdcall as a calling convention. I remember that I tried
this before but I got an exception everytime I called the function.
I guess there was some other error but now it works like this:

====================================
type
   TGetDwgName = function( Channel: Longint; FileName: PChar ): Longint; stdcall;

var
   fnFileName  : TGetDwgName;


------------------------------------------
in some init func:


      @fnFileName := GetProcAddress( m_uiLibHandle, 'GetDwgName' );


-------------------------------------------
some other func:

var
   A: array[0..MAX_PATH] of Char;
begin
   if( m_uiLibHandle <> 0 ) then
   begin
      fnFileName( ci_Channel, A );
      ViewFile( A, true );
   end;
end;


So you've pointed me in the right direction Workshop_Alex.
thx alot!

Wyverex
0
 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
You're welcome. I knew it should be something like that and just didn't understand why it didn't work. :-)

I had similar problems myself in the past, where parameters weren't changed correctly and in all cases I solved it by changing the calling convention.

But you might want to use WordBool as return code. It does seem to return a boolean and WordBool should be compatible...
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

772 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now