Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DLL H3LL AciiZ Pchar Nightmare Delph-FPC-PB

Status
Not open for further replies.

urbansound

Programmer
Sep 19, 2006
2
US
Hi from the new guy and thanks in advance to all those who help solve problems in community efforts. :)

I've been working with FreePascalCompiler in Win 9x/XP since the 1.x days, presently at FPC 2.0.2. I have a rather unique interface situation and due mostly to the manner of parameter passing of strings in Pascal, (which I've not had the prior pleasure of), I need some pointers. (ooohhh, bad pun, sorry).

It's a Dll <> DLL <> Dll configuration which while I've had various parts of it working, I'm looking for the most reliable way, for obvious reasons, not to mention FPC in Delphi mode has some unique string typcasting automation available.

PowerBasic DLL FreePascal DLL Delphi 6 DLL stub
AsciiZ strings <> My project <> via script engine
by Ref long/short string variant / shortstring

I'm hoping to focus more on the PB <> FPC part of things, which is where I've had the most trouble.

PB relies on the win32 API handling of AsciiZ which apparently works fairly transparently with most Win32 systems. e.g. in VB I could apparently just toss strings at the parameters mostly and get back strings. In Pascal, it appears I need to either setup the typcasts very carefully, or possibly set up buffer and pointer management, or there's a two-step process casting strings first as constants, perhaps and faking the compiler by tucking the strings in parenthesis to appear as an expression.

The FPC app looks like this...

Code:
{LongStrings ON}  //Or not, if we prefer

Library MyDLL;

//declare PB shared lib calls
procedure PBstringSub(s1,s2,s3,s4:pchar);external 'PBdll32.dll'  //All are byRef

//declare the Delphi interface (stuck with it)
s := DelphDLL(var Variant1,Variant2,Variant3,Variant4, var sPass:ShortString):ShortString;   //all are byRef

var s1,s2,s3,s4  :string type ?? {global variables in FPC}

//use a local proc to setup strings.
procedure DoStuff;

var sLocal1, sLocal2 :somekindofstring
begin
//setup strings with pchars or AsciiZ data?
  PBstringSub(s1,s2,s3,s4);
//reset variables for next use, different call.
end;

Exports: s1+s2+s3+s4  //Answer back to Delphi, (but not as pointers).

begin
End.

Essentially, I pass a string in from Delphi,(sPass) that calls a particular procedure in FPC. That procedure will then pass parameter structures to the PB dll, which being a byRef association will return modified data in the param list. The results coming back from PBdll are concatenated and tucked into the ShortString return value to the Delphi App where I parse the results out for use.

One issue is that the Variant data type from Delphi is quite persistent, but there are ways to solve that type conversion.

The issue has been either pre-sizing the strings in FPC before sending their pointer reference off as Pchar and/or dereferencing the data back out into strings reliably, rather than pchar pointer references (which cannot concatenate in FPC), in order to return it in the retval of the Delphi return parameter string.

In other instances, if I get the PB data to return in tact, the pchar's need to be reset for the next pass and doing so tends to make them become read-only according to the FPC docs as FPC auto dereferences them to zero if they are equated to an empty string, else I don't know what size the next call might require, or I could just load them with a dummy string on size.

So, I'm trying to do this by typecasting only and likely wasting a lot of time, shifting data between types and pointers.

Anyone care to brave a clean pass at "How would you do it?" philosopy?

Otherwise, I'll start adding more code structure if others would prefer.

Thank you in advance,

Mike
 
Im not sure that I can help much since you're doing stuff I have ventured into, but my interfaces from VB to FPC and back are all based as follows;

Code:
PROCEDURE MyProcedure(     ValueA   : PCHAR;
                       VAR ValueB   : PCHAR); stdcall; export;

VAR
ValA,ValB  : STRING;
ValBStr    : STRING;

BEGIN
    
    ValA := STRPAS(ValueA);

// Do stuff in here, convert strings to numbers etc.
// let's say we generate ValB
// then to pass out the result...

    str(ValB, ValBStr);
    ValueB:=StrAlloc(LENGTH(ValBStr)+1); 
    StrPCopy(ValueB,ValBStr);

END;

This works fine for VB to FPC and vice versa, it just uses PCHAR strings with type conversion at each end. Not very exciting, but after a lot of messing around this proved the most reliable method.

 
Thanks Stackdump,

Your example is certainly cleaner than the way I've been trying to battle it.

Let me ask this... Do you have a similar example only sending pchar's from FPC out to VB and receiving the replies? And are they DLL passing to DLL, or DLL to App or visa-versa?

Let me ramble a little here and see if you can relate to any of it...

One of the problems I'm running into is trying to reuse the pchar's but resetting them to nil apparently locks them as read only, so I only get one pass that returns valid data. I'm currently re-doing that to make sure everyone passes out of scope and gets deallocated each call. That sucks because in some cases I'm wanting to call three different functions in basic per single access inside the FPC dll, reusing the data from one call to the next, so essentially I lose that efficiency and have to pass each result out of FPC to Delphi and back in, each time.

The library function I'm going out to from FPC has in some cases, as many as 8 params and none of them show provision for sizing the data returning. With pchars that shouldn't matter if all that's returned is a pointer and then scanning that address as a char array to find the zero byte and I'm hoping to make it simply a typecast that will dereference the pointer on the fly, once they return.

In that former example, even if typecasting alone is adequate, FPC keeps converting the pchars to ansistrings automatically according to the ASM file and I have ansistrings turned off, explicitly. ??? I'm unsure if it's automatically returning them to pchar on return yet.

Another problem I'm foreseeing is that as an API, when I send my call out from FPC to Basic's external library call, it resides in a DLL dynamic memory space also, that's subject to changing based upon Window's demands between calls at any given time. Theoretically, it may return a pointer to basic's memory space as a location that is then inadvertently relocated prior to my getting the Pchar dereferenced and read back into FPC. For this reason, some articles state that reliability can only be obtained by creating a shared, common memory space on the heap, then destroy that each call.

I can link statically, however I'm thinking that in order to create a common, shared memory space, I may need to do a "loadlibrary" in FPC, then create the shared heap space, make the pass, (possibly requiring it to pass as a Tobject), which returns and then dereference/release the shared heap area. Doing that may mean having to cache FPC's present memory manager pointers, create my own, collapse it when done, and call FPC's memory manager pointers back to life, each cycle.

Any of that ring a bell? Those are just some of the things I'm picking up from far more experienced voices than my own.

Mike
 

ok, you're pushing way beyond what I have been able to do. My experience has only been from VB out to FPC and/or Dev-C. So I have VB apps that call an external DLL, push out some variables and then gather the return variables. I havent tried to drive this link from the opposite end.

From what I remember there are some Windows API functions like CreateFileMapping which allow apps to share the same memory space. I suspect you've already been down that road though.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top