Recent

Author Topic: dll usage  (Read 16863 times)

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: dll usage
« Reply #15 on: November 19, 2014, 11:24:35 pm »
Add the calling convention to your exported functions. And it's not necessary to re-declare export in your functions/procedures if they are already declared in the "export" section:
Code: [Select]
function min(x,y: integer):integer; stdcall;
...
function max(x,y: integer): integer; stdcall;
...
procedure beep; stdcall;

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: dll usage
« Reply #16 on: November 19, 2014, 11:29:53 pm »
Not allowed to upload .dll file in this forum.  Also, I cannot open mydll.lpr.   Also, I checked  minmax.dll using a hex editor.  It shows that it is 32 bit.

Put your dll file in a zip file and attach the zip file.

In MyDll.zip, you have all the necessary files to rebuild my dll:

- MyDLL.lpr: the (only) source code unit (equivalent to a .pas or a .pp file),
- MyDLL.lpi: the Lazarus project information file.

Theoretically, if you have Lazarus/Free pascal installed, double-clicking on MyDLL.lpi should open the project and display the source code unit.

** Edit ** And if you haven't installed Lazarus, "fpc MyDll.lpr" will compile and build the dll file.
« Last Edit: November 19, 2014, 11:37:28 pm by ChrisF »

jtwspoon

  • New Member
  • *
  • Posts: 11
Re: dll usage
« Reply #17 on: November 20, 2014, 12:09:09 am »
I recompiled mydll.dll. It loaded ok in autoit using dllopen  but loading minmax.dll produced a 6 error using dllopen --- The handle is invalid.  Not clear what is going on here.

srbislavr

  • Newbie
  • Posts: 1
Re: dll usage
« Reply #18 on: November 20, 2014, 12:19:21 am »
no problems loading it from heare
working code for beep

Code: [Select]
#AutoIt3Wrapper_usex64=n
$dll = DllOpen('MINMAX.DLL')
If @error Then Exit MsgBox(0,'',@error)
DllCall($dll,'none:cdecl','beep');or DllCall($dll,'none','beep') produce beep
If @error Then Exit MsgBox(0,'',@error)

im hearing the sound of some kinde, like msgbox something alerting or what ever.
« Last Edit: November 20, 2014, 12:23:06 am by srbislavr »

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: dll usage
« Reply #19 on: November 20, 2014, 12:23:08 am »
Your dll file is OK (except that the functions/procedures are not using a stdcall calling convention).

So, apparently AutoIt can use FPC Dll, if you can use mine.

I guess you could have a problem with redirection or dll location. You may eventually have several minmax.dll files; one/some for 32 bits programs and one/some for 64 bits. Especially if you've done several tests.

Try to make a new dll with a name completely different.

**Edit **  srbislavr answer seems to confirm the relocation/dll location problem specific to your configuration.
« Last Edit: November 20, 2014, 12:30:57 am by ChrisF »

jtwspoon

  • New Member
  • *
  • Posts: 11
Re: dll usage
« Reply #20 on: November 20, 2014, 12:42:26 am »
Copied minmax.pas to minmax1.pas recompiled, and still get error 6 after using dllopen on minmax1.dll in autoit.  What is the mode specification in  mydll for? Could that be the difference?

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: dll usage
« Reply #21 on: November 20, 2014, 01:28:43 am »
...What is the mode specification in  mydll for? Could that be the difference?...

Free Pascal compiler modes:
http://www.freepascal.org/docs-html/user/userse33.html

No, theoretically just for these very simple dll projects, there should be no difference.

jtwspoon

  • New Member
  • *
  • Posts: 11
Re: dll usage
« Reply #22 on: November 20, 2014, 04:24:53 pm »
OK, thanks for all the help!  I have now isolated the source(s) of my problem:
1.  The export keyword must follow the declaration of the  beep function if it is included in  the list of exported functions of the dll.
2. If the crt unit is included in a use statement (even if it is not actually needed by the following code), then the $mode directive must be included.

I think now that if either of these two conditions are not satisfied, then a 6 error will occur on loading the dll in autoit  by using DLLOpen.   When those conditions are both satisfied DLLOpen works without error on the simple dll I am testing.

jtwspoon

  • New Member
  • *
  • Posts: 11
Re: dll usage
« Reply #23 on: November 20, 2014, 06:12:50 pm »
Apparently I spoke too soon. Now I can no longer load minmax1.dll if the beep function is included in the compilation of the dll no matter what I have tried.  Seems that successful loading in autoit by DLLOpen of the dll compiled with beep function included is sporadic, sometimes it might be successful and sometimes not.

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: dll usage
« Reply #24 on: November 20, 2014, 09:27:25 pm »
...
1.  The export keyword must follow the declaration of the  beep function if it is included in  the list of exported functions of the dll.
2. If the crt unit is included in a use statement (even if it is not actually needed by the following code), then the $mode directive must be included.
...

For being honest, I can't see why any of these 2 requirements should be necessary. I'm afraid it's not really the reason of your troubles (as you last post seems to confirm it).

Of course, I don't know AutoIt. And the source code for it seems to be no more available; so, no way to see what the DLLOpen function is really doing.

Have you tried to use "personal" function names that can't interfere with known ones (min, max or beep are not): like myOwnMin, myOwnMax, and especially myOwnBeep ?

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: dll usage
« Reply #25 on: November 21, 2014, 04:37:37 pm »
After testing a few your dll file with a basic C program (using only the Windows APIs), I've got a few troubles with the cdecl calling convention.

So, I suggest you to declare your functions with the (Windows usual) stdcall convention. No more problems with it, at least for me.

Modification of your dll source code (add the stdall convention to each of your functions):
Code: [Select]
Library minmax;

uses crt,
     windows;

function min(x,y: integer):integer; stdcall;
begin
if x < y then Min:= x else min := y;
end;

function max(x,y: integer): integer; stdcall;
begin
if x > y then max:= x else max:= y;
end;

procedure beep; stdcall;
begin
  sound(220);
  delay(200);
  nosound;
end;

exports
 min index 1,
 max index 2,
 beep index 3;

begin
end.


And attached the very simple C program to test your dll (I've included the exe file -32 bits version-, in case you can't compile the C source code).
Code: [Select]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>

typedef long int (__stdcall * FUNC_MIN) (long int, long int);
typedef long int (__stdcall * FUNC_MAX) (long int, long int);
typedef void (__stdcall * FUNC_BEEP) ();

void main()
{
  HMODULE DllHandle;
  FUNC_MIN FuncMin;
  FUNC_MAX FuncMax;
  FUNC_BEEP FuncBeep;

  // Dll Loading
  DllHandle = LoadLibrary("MINMAX.DLL");

  printf("\r\n");
  if (DllHandle == NULL)
    printf("** ERROR ** Can't load MINMAX.DLL. Error = %d \r\n", GetLastError());
  else
    {
    printf("Dll loaded. \r\n");

    // Getting Functions Addresses
    FuncMin = (FUNC_MIN) GetProcAddress(DllHandle, "min");
    if (FuncMin == NULL)
      printf("** ERROR ** Can't find min function. Error = %d \r\n", GetLastError());
    else
      printf("  min function found. \r\n");

    FuncMax = (FUNC_MAX) GetProcAddress(DllHandle, "max");
    if (FuncMax == NULL)
      printf("** ERROR ** Can't find max function. Error = %d \r\n", GetLastError());
    else
      printf("  max function found. \r\n");

    FuncBeep = (FUNC_BEEP) GetProcAddress(DllHandle, "beep");
    if (FuncBeep == NULL)
      printf("** ERROR ** Can't find beep function. Error = %d \r\n", GetLastError());
    else
      printf("  beep function found. \r\n");

    // Testing functions
    printf("\r\n");
    if (FuncMin)
      printf("  min of 29 and 54 = %ld \r\n", FuncMin(29 ,54));
    if (FuncMax)
      printf("  max of 12 and 109 = %ld \r\n", FuncMax(12 ,109));
    if (FuncBeep)
      {
      printf("  beep");
      FuncBeep();
      }
    printf("\r\n");

    // Dll Closing
    FreeLibrary(DllHandle);
    }
}
« Last Edit: November 21, 2014, 04:43:48 pm by ChrisF »

jtwspoon

  • New Member
  • *
  • Posts: 11
Re: dll usage
« Reply #26 on: November 21, 2014, 06:37:06 pm »
Thanks very much!  I have things working now.  you are correct -- the two restrictions I identified earlier as necessary to load the dll in autoit are not critical  --- the dll does load ok,  I was confused by the _WinAPI_GetLastError function returning 6 when either of these two conditions were not satisfied, even though the dll did load successfully and was usable.  It is still puzzling to me why the  _WinGetLastError function returned nonzero in those cases, but probably should not worry about it.

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: dll usage
« Reply #27 on: November 21, 2014, 08:08:40 pm »
...
It is still puzzling to me why the  _WinGetLastError function returned nonzero in those cases, but probably should not worry about it.

Well, to make it short GetLastError() is meaningless when you've not got en error: in your case, -probably- when the result of DllOpen is not -1.

The problem is that some "internal" system functions may eventually set the GetLastError() value to non zero, even it they succeed. Furthermore, some of them set it to zero when it's OK, while some other don't; so the error result is coming in fact from another call.

See here for more information:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360%28v=vs.85%29.aspx

And we still don't know which API(s) are called by DllOpen; may be not only LoadLibray/LoadLibraryEx.


 

TinyPortal © 2005-2018