Delphi-DLL for VB

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;


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
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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.



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:


Good luck!!


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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;

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

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

Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

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.


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

Good luck!!

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

and back, String to pChar i use

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

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

  A := 100;
  B := 200;

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

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

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


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

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

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


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:

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

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

any ideas ?
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.