Solved

using Delphi DLL in C#

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

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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Bit flags and bit flag manipulation is perhaps one of the most underrated strategies in programming, likely because most programmers developing in high-level languages rely too much on the high-level features, and forget about the low-level ones. Th…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

932 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now