Solved

DLL call doesn't work

Posted on 2004-08-09
9
241 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
[X]
Welcome to Experts Exchange

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

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 2
9 Comments
 
LVL 12

Expert Comment

by:Ivanov_G
ID: 11751772
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
ID: 11751782
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
ID: 11751813
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

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

 

Author Comment

by:Wyverex
ID: 11751878
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
 
LVL 17

Expert Comment

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

Tried that already?
0
 

Author Comment

by:Wyverex
ID: 11752413
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
ID: 11752526
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
ID: 11753339
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
ID: 11757397
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

Technology Partners: 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!

Question has a verified solution.

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

Suggested Solutions

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
How to Install VMware Tools in Red Hat Enterprise Linux 6.4 (RHEL 6.4) Step-by-Step Tutorial

732 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