Solved

using Delphi DLL in C#

Posted on 2003-11-16
9
701 Views
Last Modified: 2010-04-16
I want to use a delphi DLL in my C# program, but am having a problem.
Delphi function prototype (LongInt has size od 4 bytes in Delphi):

FUNCTION _Status_Cmd(    PortIndex  : LongInt;
                                 DevAddr    : LongInt;
                             VAR Data       : ARRAY OF LongInt): LongInt;       STDCALL;


Then, in my C program, I have:

[DllImport("comcom32.dll", ExactSpelling=false, SetLastError=true)]
private static extern int _Status_Cmd(int PortIndex, int DevAddr, int[] Data);

...


int[] iData = new int[100]; (in delphi example, iData is set to 100 zero elements, too)
int PortIndex = 1, ret;

ret = _Status_Cmd(PortIndex, 0, iData);

After return, data should be like this:

5 0 32 132 142 0 0 0 0 .......

as is the case, if I use this function in Delphi, but if I use the function in my C# program, I get this:

5 0 0 0 0 0 0 0 0 ........ (all zeroes, except first element in int array)

So, only the first element is set correctly, others are left alone. I tried with various marshalling functions, but with no success so far.

All suggestions appreciated.
0
Comment
Question by:Sagadin
  • 5
  • 2
  • 2
9 Comments
 
LVL 18

Expert Comment

by:testn
ID: 9758594
Try

[DllImport("comcom32.dll", ExactSpelling=false, SetLastError=true)]
private static extern int _Status_Cmd(int PortIndex, int DevAddr, [MarshalAs(UnmanagedType.LPArray, SizeConst=100)] int[] Data);
0
 

Author Comment

by:Sagadin
ID: 9758639
Thank you for your quick response. Yes, I have tried this MarshalAs function before, now again, but it doesn't work. Still the same problem. :(
0
 
LVL 18

Expert Comment

by:testn
ID: 9758754
how about?

[DllImport("comcom32.dll", ExactSpelling=false, SetLastError=true)]
private static extern int _Status_Cmd(int PortIndex, int DevAddr, [MarshalAs(UnmanagedType.LPArray, SizeConst=100)] [in,out] int[] Data);

0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

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

 

Author Comment

by:Sagadin
ID: 9759011
don't know if I understand you correctly.

If I use:

private static extern int _Status_Cmd(int PortIndex, int DevAddr, [MarshalAs(UnmanagedType.LPArray, SizeConst=100)] in int[] Data);

I get compiler error (Type expected). If I use:

private static extern int _Status_Cmd(int PortIndex, int DevAddr, [MarshalAs(UnmanagedType.LPArray, SizeConst=100)] out int[] Data);

it compiles fine, but when program is run, an exception occurs:

----
An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in test.exe

Additional information: Can not use SizeParamIndex for byref array parameters.
---

So I deleted the ...SizeConst=100... part, this time program gives me the exception:

---
An unhandled exception of type 'System.NullReferenceException' occurred in test.exe

Additional information: Object reference not set to an instance of an object.
---
0
 

Author Comment

by:Sagadin
ID: 9759090
Oh, now I tried:

[DllImport("comcom32.dll", ExactSpelling=false, SetLastError=true)]
private static extern int _Status_Cmd(int PortIndex, int DevAddr, [MarshalAs(UnmanagedType.LPArray, SizeConst=100)] [In,Out] int[] Data);

But still the same. Even tried [In] [Out] and [Out,In], result always the same, only first int is set.
0
 
LVL 10

Expert Comment

by:ptmcomp
ID: 9800389
How about this:

[DllImport("comcom32.dll", ExactSpelling=false, SetLastError=true)]
private static extern int _Status_Cmd(int PortIndex, int DevAddr, IntPtr addrIntArray);


IntPtr addrIntArray;

addrIntArray = Marshal.AllocHGlobal(100*4); // 100 * sizeof(Int32)
int ret = _Status_Cmd(portIndex, devAddr, ref addrIntArray); // try also without ref

Int32[] result = new Int32[100];
Marshal.Copy(addrIntArray, result, 0, 100);

0
 

Author Comment

by:Sagadin
ID: 9802757
I'm afraid still no success, now the "result" array looks like this:

5  782282168 78299680 78301820 78301956 ......

So again, only the first int is OK. Any other ideas? I ran out of mine... :(
0
 
LVL 10

Accepted Solution

by:
ptmcomp earned 125 total points
ID: 9802850
How about:

IntPtr addrIntArray;

Int32[] result = new Int32[100];
addrIntArray = Marshal.AllocHGlobal(100*4); // 100 * sizeof(Int32)
Marshal.Copy(result, 0, addrIntArray, 100);
int ret = _Status_Cmd(portIndex, devAddr, addrIntArray); // try also with ref
Marshal.Copy(addrIntArray, result, 0, 100);
0
 

Author Comment

by:Sagadin
ID: 9802896
Thank you both for help. The problem was in DLL, delphi prototype has only three fields defined and it works fine when compiled with Delphi. Now I got a C++ .h file and in it has also an additional function argument which is obviously needed when library is used with C# or C++:

_Status_Cmd(portIndex, devAddr, addrIntArray, 100);

So, I've been calling it with one actual argument too little. Works for Delphi, but not for C#.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

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

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In order to hide the "ugly" records selectors (triangles) in the rowheaders, here are some suggestions. Microsoft doesn't have a direct method/property to do it. You can only hide the rowheader column. First solution, the easy way The first sol…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question