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

Delphi-DLL for VB

Hello,
I have to create a DLL in Delphi, which is used as API for a Windows NT-Service (also Delphi). The Client-Program which is going to use this DLL will written in Visual Basic 6.0

Now I have some Questions on the Compatibility. The last few Days I was reading Articles in MSDN and TechNet about technical Issues of Visual Basic and I've found compatible Data-Types for the most numeric Types we are going to use.

But what I'm not sure about are the Strings. I know I'll have to use pChar to avoid Problems with Delphi's String Memory Managment.

But how could a Function look like, which returns a pChar with variable Lenght are takes/gives a pChar as Parameter ?

I read in technical Docs, that VB creates a temporary copy of the string declared by the VB-Programmer in the format of the C-Language, so it's a null-terminated pChar and passes the DLL-Function a Pointer to it.
Therefore, i should be able to implement the string-support just like the API does.

could it be something like this ?

function ReturnStr(var AvaiableByteFromHostApp, RequiredBytesByDLL : Integer) : pChar;

and

function GetString(var Buffer : pChar) : Integer;

here the function result would be the length of the string, the Functions are delcared as stdcall...of course :)

Another Thing is, do I need to include the ShareMem-Unit and publish the DLL with the BorlandMM.DLL (which i dont want) also, if i use just Delphi-Strings internally in the DLL and convert them into pChars whenever they are exported from the DLL, or would that not affect the entire thing ?

thx, Roger
0
omsec
Asked:
omsec
  • 4
  • 3
1 Solution
 
rwilson032697Commented:
As you are using a DLL, allocation of memory for the PChars is not a major problem, PROVIDED that someone knows who is allocating and who is freeing.

However, is you are using strings in the DLL, and then passing a string cast to a PChar back through the DLL interface then you may be asking for trouble as the string may be freed by the DLL at any time while the caller is still expecting to be able to access the memory (moral of the story: never pass a string across a DLL boundary, unless the app and the DLL are bult with Delphi)

In your case, you will not need to use sharemem or borlndmm.dll, unless you have other Delphi DLLs you want to share strings with.

Cheers,

Raymond.

0
 
DrDelphiCommented:
So many questions, so little time... <g>


You have the right idea with the Returnstr function... essentially you want to know internally to the dll what the size is of the string being passed in is. So, you have a String parameter, followed by a size parameter. On the VB side, you want to make sure that if you are returning literals longer than 255 characters, that you DIM them:

dim ret as string *1500


As for the shareMem... you need not distribute it ever solong as you pas only Pchar in and out of the DLL, internally you can use either string or pchar interchangeably, although if you use Pchar, you will have to make sure to allocate sufficient memory for a large string:

GetMem(DLLresult,1500);



Good luck!!

0
 
omsecAuthor Commented:
I know GetMem, I used it former under Borland Pascal 7. The Delphi Help said I should use StrAlloc and StrDispose.

Is there any difference between GetMem/FreeMem and Strxxxxx Procs ?

So this should not require BorlandMM.dll, right ?

function ReturnString(var strBuf :    Integer; var clBuffer : Integer) : pChar; stdcall;

var
  HelpStr : string; // local, maybe assigned to a global var later in the DLL
  HelpVar : Integer;

begin
  HelpStr := 'Hello World!';
  clBuffer := Length(HelpStr);
  if strBuf < clBuffer then
    begin
    ....

thx
0
Learn to develop an Android App

Want to increase your earning potential in 2018? Pad your resume with app building experience. Learn how with this hands-on course.

 
DrDelphiCommented:
Both StrAlloc and StrDispose are being kept around for backward compatibility. The GetMem function is valid for ANY pointer, therefore making it (at least as far as I am concerned) preferable.
and yes, your function looks fine...except of course when look at the length of Helpstr, you should subtract 1 for the null terminater.

clBuffer:=Lenght(HelpStr)-1;


this way you won't run into trouble later pasing it back out as Pchar.



Good luck!!


0
 
omsecAuthor Commented:
so I have to allocate memory for the string also ??
I thought the Host-App does that and gives me the Pointer to that Mem.

To convert pChar to String i use
StrPas

and back, String to pChar i use
StrPcopy

is that good ?
0
 
omsecAuthor Commented:
In Visual Basic I get an Access Violation when calling the Function

procedure ExchangeData(var A : Integer; var B: Integer); stdcall;

begin
  A := 100;
  B := 200;
end;

In Delphi it works.
Do I have to change it to make it run in VB 6 ?
0
 
DrDelphiCommented:
Does your declaration look like this in VB?

Private Declare Sub ExchangeData Lib "mydll.dll"(byval A as integer,Byval B as integer)




0
 
omsecAuthor Commented:
exactly.
i replaced ByVal with ByRef now it works. But nested strings (a string in a record make me still problems:

[Delphi/DLL]

type
  TMyStruct = packed record
                StrucSize : Cardinal;
                clName : Cardinal;
                Name : pChar;
                Age : Byte;
                Flags : Cardinal;
              end;  

function GetStruc(var Buffer : TMyStruct) : Integer; stdcall;

var
  HelpVar : Integer;
 
begin
  if @Buffer <> NIL then
    begin
      with Buffer do
        begin
          Name := 'Roger Bieri';
          clName := Length(Name) + 1;
          Age := 18;      
          Flags := 1000;
          HelpVar := 13;
          inc(HelpVar, clName);
          StrucSize := HelpVar;
         end;
      Result := 0;
    end
  else
    begin
//      @Buffer := NIL;
      Result := -1;
    end;
end;

[VB/HOST]

Public Type TMyStruc
              StrucSize As Long
              clName As Long
              Name As String * 500
              Age As Byte
              Flags As Long
End Type

Public Declare Function GetStruc Lib "mytest.dll" (ByRef Buffer As TMyStruc) As Long


To return a String als Function-Result does also fail. Returning a Stirng over a Function-Parameter works:

fail:
Public Declare Function ReturnString Lib "mytest.dll" (ByRef clBuffer As Long, ByRef szBuffer As Long) As String

work:
Public Declare Function GetString Lib "mytest.dll" (ByRef clBuffer As Long, ByRef szBuffer As Long, ByRef Buffer As String) As Long

any ideas ?
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now