Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / July 2007

Tip: Looking for answers? Try searching our database.

Problems with DllImport and a Delphi native DLL.

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Thomas Due - 04 Jul 2007 10:07 GMT
Hi,

I manage an rather old application in which we have some fairly complex (ugly) Delphi code. This is Delphi 6 we're talking about.

Among all this Delphi code there is method for formating a print layout for slip printers. Pass a few parameters to this method and it returns a Delphi string which contains the entire slip, ready for sending to the slip printer.

Now, we're slowly migrating to .NET and am in need of printing this slip from a .NET application. However instead og re-inventing the wheel for generating this slip, we'd like to create a simple DLL in Delphi which is then consumed by the .NET application.

However, this has turned out to pose a few problems.

=====================================================
My first attempt at this:

-------------------------
Delphi method prototype:
------------------------
function GetSlipData(
    ARegNo: integer;
    APrinterID: integer;
    ASlipNo: integer) : string; stdcall;

-------------------------
C# DllImport declaration:
-------------------------
[DllImport("SlipPrint.dll",
    CharSet = CharSet.Ansi,
    CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern string GetSlipData(
    int regNo,
    int printerId,
    int slipId);

This results in a

"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Access violation exception.

So, I research and discover that I can't apparently return strings to .NET application through p/invoke, as "strings are immutable". Fair enough, I try using a StringBuilder instead.

=====================================================
My second attempt at this:

-------------------------
Delphi method prototype:
------------------------
function GetSlipData(
    AEkspNr: integer;
    APrinterID: integer;
    ASlipNo: integer;
    var output : string) : integer; stdcall;

-------------------------
C# DllImport declaration:
-------------------------
[DllImport("SlipPrint.dll",
    CharSet = CharSet.Ansi,
    CallingConvention = CallingConvention.StdCall)]
internal static extern int GetSlipData(
    int regNo,
    int printerId,
    int slipId,
    [MarshalAs(UnmanagedType.LPStr)]StringBuilder output);

Now I don't get any exceptions, the method returns the correct length of the string, but the StringBuilder only contains five characters.

You see, the string may very well contain null characters, so how on earth do I solve this problem?

How do I pass a string that may contain null characters from a Delphi DLL to a .NET application?

Signature

Thomas Due
Posted with XanaNews version 1.18.1.6

"If you want a friend in Washington, get a dog."
-- Harry S. Truman

Mathieu Cartoixa - 04 Jul 2007 12:37 GMT
Thomas Due a écrit :
> Hi,
>
[quoted text clipped - 34 lines]
>
> Access violation exception.

From what I can remember, strings in Pascal (Delphi) are prefixed by
their length, and are allocated (and freed) by specific functions (in
the ShareMem unit).
This conflicts with the definition of strings in .NET, which are null
('\0') terminated, and allocated (and freed) by the .NET environment.

In your case, you want the delphi code to allocate a string, and the
.NET environment (GC) to free it automatically. So you have to choose a
string format that is recognized by both sides : BSTR.

1. Make a wrapper in Delphi for your function that return a BSTR (cf.
http://groups.google.com/group/borland.public.delphi.objectpascal/msg/da2ff65788
6892ff
).
2. Change your return type attribute to [MarshalAs(UnmanagedType.BStr)]
or [MarshalAs(UnmanagedType.AnsiBStr)] (you will have to determine this
by yourself).

That is all, your original BSTR will be automatically freed by the .NET
environment, calling the proper system API.

> So, I research and discover that I can't apparently return strings to .NET application through p/invoke, as "strings are immutable". Fair enough, I try using a StringBuilder instead.

I am pretty sure you can. The truth is elsewhere...

> =====================================================
> My second attempt at this:
[quoted text clipped - 25 lines]
>
> How do I pass a string that may contain null characters from a Delphi DLL to a .NET application?

See my answer above. Had there been no null character in your string,
you would very likely have got an exception as well.

                 Mathieu

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.