We help IT Professionals succeed at work.

trying to use C++ Dll

poxy
poxy asked
on
Medium Priority
473 Views
Last Modified: 2011-09-20
hi.. I have a c++ dll that exports this function:

ULONG PacketGetAdapterNames(PTSTR pStr, PULONG BufferSize)

This is what I have done so far, but is doesn't work:

procedure TForm1.Button1Click(Sender: TObject);
  var hndDllHandle : Thandle;
  var AdapterName : pChar;
  var AdapterLength : longint;
  var strDllName : pChar;
  PacketGetAdapterNames: function(PTSTR:Pointer; PULONG:pointer):longint stdcall;
begin
  strDllName := 'wpcap.dll';
  AdapterName := StrAlloc(512);
  AdapterLength := 512;

  hndDllHandle := loadlibrary(strDllName);
  if (hndDllHandle = 0) then
    MessageDlg('Unable to LoadLibrary(''' + strDllName +  ''')',mtError,[mbOK],0)
  else
    begin
      MessageDlg('Library loaded successfully!',mtInformation,[mbOK],0);
      PacketGetAdapterNames := GetProcAddress(hndDllHandle, 'PacketGetAdapterNames');
      PacketGetAdapterNames(AdapterName,@AdapterLength);
    end;
  freelibrary(hndDllHandle);
end;
Comment
Watch Question

Give this a try, you're basically there.

Unit test;
.
.
.
Function PacketGetAdapterNames : String;


Inmplementation

Type
  TPacketGetAdapterNames = Function( pstr : PChar, Buffersize : DWord ) : DWord; stdCall;


Function PacketGetAdapterNames : String;
var
  hndDllHandle : Thandle;
  AdapterName : pChar;
  AdapterLength : longint;
  strDllName : pChar;
  vPacketGetAdapterNames : TPacketGetAdapterNames;
begin
  strDllName := 'wpcap.dll'; //DLL Must be in the same directory as the exe. (lies to children)

  AdapterName := StrAlloc(512);
  AdapterLength := 512;

  hndDllHandle := loadlibrary(strDllName);
  if (hndDllHandle = 0)
  then MessageDlg('Unable to LoadLibrary(''' + strDllName +  ''')',mtError,[mbOK],0)
  else begin
         MessageDlg('Library loaded successfully!',mtInformation,[mbOK],0);
         vPacketGetAdapterNames := GetProcAddress(hndDllHandle, 'PacketGetAdapterNames');
         If vPacketGetAdapterNames <> nil
         Then vPacketGetAdapterNames(AdapterName, AdapterLength )
         Else MessageDlg('cannot find procedure!',mtError,[mbOK],0)
       end;
  freelibrary(hndDllHandle );

  //Move the Adaptername to somewhere else now to avoid a memory leak
  Result := StrPas( AdapterName );

  StrDispose( AdapterName );
End;


if this doesn't work, what's the error message?

Colin Dawson.

Author

Commented:
I'll try this when i get home, and let you know.
Function( pstr : PChar; var Buffersize : DWord ) : DWord; stdCall;

Commented:
Building on Colin's code....
I think you should add a few type declarations just to be
sure - I suspect that the C++ expects a pointer to a ULONG (Cardinal) not the actual ULONG.
so.....

const
  PACKETDLL = 'wpcap.dll';

type
  ULONG = Cardinal;
  PULONG = ^ULONG;
  PTSTR = PChar;
  TPacketGetAdapterNames = function(pStr: PTSTR; BufferSize: PULONG): ULONG; stdcall;


function PacketGetAdapterNames: string;
const
  BUFSIZE = 512 + 1;
var
  hndDllHandle: THandle;
  AdapterName: PTSTR;
  AdapterLength: PULONG;
  strDllName: PChar;
  vPacketGetAdapterNames: TPacketGetAdapterNames;
begin
  strDllName := PChar(PACKETDLL);
  AdapterName := StrAlloc(BUFSIZE);
  New(AdapterLength);
  AdapterLength^ := BUFSIZE;

  hndDllHandle := LoadLibrary(strDllName);
  if hndDllHandle = 0 then
    MessageDlg('Unable to LoadLibrary(''' + strDllName + ''')',mtError,[mbOK],0)
  else
  begin
    vPacketGetAdapterNames := GetProcAddress(hndDllHandle, 'PacketGetAdapterNames');
    if vPacketGetAdapterNames <> nil then
      vPacketGetAdapterNames(AdapterName, AdapterLength)
    else
      MessageDlg('Cannot find procedure!',mtError,[mbOK],0);
  end;
  FreeLibrary(hndDllHandle);
  Result := StrPas(AdapterName);
  StrDispose( AdapterName );
  Dispose(AdapterLength);
End;
robert_marquardt: DOH, I always forget about the VAR when it's a pointer type paramters.  Think I really should learn C++ someday. he he.
Commented:
Hi poxy.

This is what I once used.

function pcap_lookupdev(var ErrStr:string) : pchar;
var   NameLength   : integer;
      AdapterNames : array[0..1024-1] of char;
      WadapterNames: array[0..1024-1] of widechar;
      i            : integer;
      AdapterName1 : Pchar;
      S            : string;
      Ver          : Twinversion;
begin
   NameLength := 1024;
   Ver := pcap_GetwinVersion(S);
 
   // WINDOWS 95 or 98
   if (Ver=wv_Win95) OR (Ver=wv_Win98) then
   begin
     GetMem(AdapterName1,NameLength);
     PacketGetAdapterNames(AdapterNames,@NameLength);
     i:=0;
     While i<NameLength do
     begin
       if AdapterNames[i]=' ' then AdapterName1[i]:=#0
                             else AdapterName1[i]:= AdapterNames[i];
       if AdapterNames[i]=#0 then break else inc(i);
     end;
 
     AdapterName1[i-1] := #0;
     AdapterName1[i+1] := #0;
     AdapterName1[i]   := #0;
 
     result := Adaptername1;
   end
 
   // WINDOWS NT OR 2000
   Else if (ver=wv_winNT) or (ver=wv_win2000) then
   begin
     Getmem(AdapterName1,1024*Sizeof(char));
     PacketGetAdapterNames(Pchar(@wAdapterNames),@NameLength);
 
     for i:=0 to NameLength-1 do
     begin
       if (Wadapternames[i]=#0)and(wadapternames[i+1]=#0) then break;
       AdapterName1[i] := char(wAdapterNames[i]);
     end;
 
     result := adaptername1;
   end;
 
end;

This code is taken from the following webpage:
http://home1.stofanet.dk/nitezhifter/

They have some information about this.
Colin_Dawson: To be able to use var you need documentation, but here a guess at a standard Microsoft parameter pattern is good enough.
poxy: did you try it?  does it work?

Author

Commented:
The version Rondi posted worked, but it did not return the right result. With a code from hagur's post was I able to get it to work.
Now i'm very confused about whom I should give the points.

But I think hagur's post made the difference so I will revard him the points.