I'm looking for RTL delphi function equivalent to the sscanf/swscanf C++ functions. Exist something like that in the RTL delphi functions or I must look for a third-party implementation?
I personally would simply call the real functions which can be imported from msvcrt.dll.
function sscanf(buffer, format: PAnsiChar): Integer;
cdecl; varargs; external 'msvcrt.dll';
function swscanf(buffer, format: PWideChar): Integer;
cdecl; varargs; external 'msvcrt.dll';
These are tried and tested robust implementations of the C standard library functions.
You can download Scan function for Delphi, which is ported MSVC RTL function.
There's a port of sscanf at http://cc.embarcadero.com/item/24258 but it looks to pre-date Unicode so may need some tweaks for XE.
These are deprecated functions even in C. Use something more modern and type-safe to parse your data. This is going to be a rich source of errors in your application. For example, how do you intend to make a (wchar_t *) C style scanf string function interoperate with Delphi Strings?
Related
I need to create a dll within fpc (delphi-mode). It works fine - but for some reasons, I want to do something (in a unit) like
function doSomeThing(a:type1):type2;stdcall;
function doSomeThing(a:type3):type4;stdcall;
and in the library (for building the dll using the unit above)
exports
doSomeThing(a:type1) name 'doSomeThingTYPE1',
doSomeThing(a:type3) name 'doSomeThingTYPE3';
The syntax is self explanatory and is told in How to export Overload functions from DLL? . But it seems to be unavailable in fpc (version 2.6.0-9 [2013/04/14] for x86_64). Is there a chance to do something like that - or do I have to rename the functions within my source?
The question that you link to discusses Delphi. The syntax that Delphi supports, that allows you to export overloaded functions, is not supported by FPC.
To the best of my knowledge, overloaded functions are not exportable. Although, I could easily be wrong on that score. Perhaps there is a way, as Marco proposes in his answer.
David consulted me in another thread, I devised something that compiles, but don't know if it works.
It is based on exporting the function using a defined linker level identifier, and then declaring an external function reimporting it with different Pascal names. Note that bla and bla2 doesn't even have to be in the same unit as dosomething variants.
library testdll;
{$mode delphi}
type
type1=integer;
type3=char;
type2=smallint;
type4=widechar;
function doSomeThing(a:type1):type2;stdcall; overload; [public, alias:'bla'];
begin
result:=a+1;
end;
function doSomeThing(a:type3):type4;stdcall; overload; [public, alias:'bla2'];
begin
result:=widechar(ord(a)+1000);
end;
procedure bla; external name 'bla';
procedure bla2; external name 'bla2';
exports
bla name 'doSomeThingTYPE1',
bla2 name 'doSomeThingTYPE3';
end.
I am reading the documentation for MoPaQ and trying to convert the functions over to Delphi because some of the data types mentioned in the documentation do not directly match the ones in Delphi.
This is the function I am having troubles with:
HANDLE WINAPI MpqOpenArchiveForUpdate(LPCSTR lpFileName, DWORD dwCreationDisposition, DWORD dwHashTableSize);
In Delphi, I have converted it as:
function MpqOpenArchiveForUpdate(lpFileName: Char, CreationDisposition, dwHashTableSize: LongWord); external 'lmpqapi.dll';
I am missing the return type for my function which I believe is HANDLE (according to the documentation). If that is the case, what is the Delphi equivalent for the HANDLE data type?
The equivalent would be something along these lines:
function MpqOpenArchiveForUpdate(lpFileName: LPCSTR;
dwCreattionDisposition,
dwHasTableSize: DWord): THandle; stdcall; external 'lmpqapi.dll';
Note that you'll have to find out if MoPacQ is Unicode-aware or not; if it's not, change the definition of lpFileName to PAnsiChar instead.
Remy points out in his comment below that Delphi maps LPCSTR to the proper PAnsiChar type on all versions, so you should use it that way.
I need to wrap some legacy code in Delphi 7 for use within Delphi XE2. My question seems simple, but I tried ALL the examples I could find and they all fail. Basically, I need to be able to pass strings between D7 and DXE2, and as far as I can figure out, the safest approach is to use pchar (since I do not want to ship the borlandmm dll).
So DLL written in D7, to be called by Delphi XE2
My interface needs to be
IN My DLL:
function d7zipFile(pFatFile,pThinFile : PChar) : integer; stdCall;
function d7unzipfile(pThinFile,pFatFile : PChar) : integer; stdCall;
I need to pass BACK the pFatFile name in the unzipfile function.
In My calling code:
function d7zipFile(pFatFile,pThinFile : PChar) : integer; external 'd7b64zip.dll';
function d7unzipfile(pThinFile,pFatFile : PChar) : integer; external 'd7b64zip.dll';
Could someone please assist with the best way to implement these?
Obviously I am not looking for the actual zip/unzip code - I have that working fine within D7. I want to know how to declare and work with the string / pchar params, since the various types I tried (PWideChar, WideString, ShortString etc) all give errors.
So I would be happy to simply be able to do a showMessage in the d7zipFile function for both filenames.
And then be able to do a showMessage in delphiXE2 on the pFatFile variable, which means the strings went both ways OK?
By far the easiest way to do this is to use WideString. This is the Delphi wrapper around the COM BSTR type. Dynamic allocation of the string payload is done using the shared COM allocator. Since the Delphi RTL manages that, it is transparent to you.
In the Delphi 7 code you declare your functions like this:
function d7zipFile(const FatFile, ThinFile: WideString): integer; stdcall;
function d7unzipfile(const ThinFile: WideString; var FatFile: WideString):
integer; stdcall;
In your calling code you declare the functions like this:
function d7zipFile(const FatFile, ThinFile: WideString): integer; stdcall;
external 'd7b64zip.dll';
function d7unzipfile(const ThinFile: WideString; var FatFile: WideString):
integer; stdcall; external 'd7b64zip.dll';
The alternative to this approach is to use PAnsiChar or PWideChar. Note that you cannot use PChar because that alias refers to different types depending on which version of Delphi you use. In Delphi 7 PChar is an alias for PAnsiChar, and in XE2 it is an alias for PWideChar.
The big downside of using PAnsiChar, say, is that the caller needs to allocate the string which is returned from the DLL. But typically the caller does not know how large that string needs to be. There are a variety of solutions to the problem but the neatest approach is always to use a shared allocator. You state that you do not want to rely on borlandmm.dll and so the next most obvious common allocator is the COM allocator. And that's why WideString is attractive.
I would like to build a custom setup, with an aero form, but I don't know how to start it.
Is there any way to use DWM API with inno setup?
function dwm(Wnd: HWnd; cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight: integer ): Longint; external 'DwmExtendFrameIntoClientArea#dwmapi.dll stdcall';
DWM API is a native API so you can access it using the DLL Import method.
Then you can call API functions in your script code.
But I would recommend against doing this. Since the DWM only works on Vista or later and it can be disabled by stopping the NT Service. It could prevent your installation from working on a machine that it was designed to work on.
Now that you posted your code...
Original declaration of the API you posted.
HRESULT WINAPI DwmExtendFrameIntoClientArea(
HWND hWnd,
__in const MARGINS *pMarInset
);
My best guess is that it should look like this instead.
type
Margins = record
cxLeftWidth : Integer;
cxRightWidth: Integer;
cyTopHeight: Integer;
cyBottomHeight: Integer;
end;
function DwmExtendFrameIntoClientArea(Wnd: HWnd;
var pMarInset : MARGINS) :
HRESULT;
external 'DwmExtendFrameIntoClientArea#dwmapi.dll cdecl';
you can use the third party tool ISSkin for inno setup
http://isskin.codejock.com/
hope this helps
I would not use such an approach in a setup program, but if you you really need it I would develop it in Delphi, wrap it in a DLL with a simpler API, and call that DLL from InnoSetup.
We try to pass a string from a native Delphi program to a Delphi Prism DLL.
We have no problem passing integers, but strings are mismatched in the DLL.
We saw Robert Love's code snippet in response to another question, but there is no code for the native Delphi program.
How can we pass strings from Delphi to a Delphi Prism DLL?
The best way would be to use WideString.
For several reasons.
It is Unicode and works before D2009
It's memory is managed in ole32.dll, so no dependency on either Delphi's memory manager or the CLR GC.
You do not have to directly deal with pointers
In Oxygene, you could write it like so:
type
Sample = static class
private
[UnmanagedExport]
method StringTest([MarshalAs(UnmanagedType.BStr)]input : String;
[MarshalAs(UnmanagedType.BStr)]out output : String);
end;
implementation
method Sample.StringTest(input : String; out output : String);
begin
output := input + "ä ~ î 暗";
end;
"MarshalAs" tells the CLR how to marshal strings back and forth. Without it, strings are passed as Ansi (PAnsiChar), which is probably NOT what you would want to do.
This is how to use it from Delphi:
procedure StringTest(const input : WideString; out output : WideString);
stdcall; external 'OxygeneLib';
var
input, output : WideString;
begin
input := 'A b c';
StringTest(input, output);
Writeln(output);
end.
Also, never ever use types, that are not clearly defined, for external interfaces.
You must not use PChar for DLL imports or exports. Because if you do, you will run into exceptions when you compile it with D7 or D2009 (depending on what the original dev system was)
Strings in Delphi Win32 are managed differently from strings in .Net, so you can not pass a .Net string to Delphi Win32 or vice versa.
To exchange strings values you'd better use PChar type which is supported by both compilers. That is the same way you send string values to Windows API functions.
Regards
P.S. I am NOT Robert ;-)