Solved

using Delphi DLL in C#

Posted on 2003-11-16
9
706 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

729 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