Solved

using Delphi DLL in C#

Posted on 2003-11-16
9
705 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

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!

Question has a verified solution.

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

This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
This video shows how to use Hyena, from SystemTools Software, to update 100 user accounts from an external text file. View in 1080p for best video quality.

738 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