Port DllImport from VB to C#

P

paul f

do you knoe how to implement this VB import properly in C#?

VB:
Public Declare Function dscDIOSetConfig Lib "dscud.dll" (ByVal board
As Short, ByVal config_bytes As IntPtr) As Byte

my attempt:
[DllImport("C:\\dscud.dll", EntryPoint = "dscDIOSetConfig")]
public static extern byte dscDIOSetConfig(short board, IntPtr
config_bytes);


thanks,
Paul Foran
 
A

Alberto Poblacion

paul f said:
do you knoe how to implement this VB import properly in C#?

VB:
Public Declare Function dscDIOSetConfig Lib "dscud.dll" (ByVal board
As Short, ByVal config_bytes As IntPtr) As Byte

my attempt:
[DllImport("C:\\dscud.dll", EntryPoint = "dscDIOSetConfig")]
public static extern byte dscDIOSetConfig(short board, IntPtr
config_bytes);


An automatic translator provides this:

using System.Runtime.InteropServices;
...
[DllImport("dscud.dll", CharSet = CharSet.Ansi, SetLastError = true,
ExactSpelling = true)]
public static extern byte dscDIOSetConfig(short board, IntPtr
config_bytes);


Which should behave mostly the same as what you wrote, except for the
path to the dll. ¿What kind of trouble is it giving to you?
 
P

paul f

Hi all,

I am getting two errors when i try to call dscDIOSetConfig external
function:
Error 1 The best overloaded method match for
'dllimport.Program.dscDIOSetConfig(short, System.IntPtr)' has some
invalid arguments C:\YB\dllimport\dllimport\Program.cs 25 21 dllimport
Error 2 Argument '2': cannot convert from 'int[]' to 'System.IntPtr' C:
\YB\dllimport\dllimport\Program.cs 25 44 dllimport

here is my code:
============

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace dllimport
{
class Program
{


[DllImport("C:\\dscud.dll", CharSet = CharSet.Ansi,
SetLastError = true,
ExactSpelling = true)]
public static extern byte dscDIOSetConfig(short board, IntPtr
config_bytes);

public static void Main(string[] args)
{
byte result;
short board; //Handle of the Digital I/O board to operate
on
int[] config_bytes = new int[2];
config_bytes[0] = 0x9b; // Set all ports on first chip to
input
config_bytes[1] = 0x80; // Set all ports on second chip to
output

//board is a "C" handle, I just assigned an arb no (300)
so that I can test compile this app.
result = dscDIOSetConfig(board, config_bytes);


}
}
}
 
A

Alberto Poblacion

paul f said:
I am getting two errors when i try to call dscDIOSetConfig external
function:
Error 1 The best overloaded method match for
'dllimport.Program.dscDIOSetConfig(short, System.IntPtr)' has some
invalid arguments C:\YB\dllimport\dllimport\Program.cs 25 21 dllimport
Error 2 Argument '2': cannot convert from 'int[]' to 'System.IntPtr' C:
\YB\dllimport\dllimport\Program.cs 25 44 dllimport
[...]
public static extern byte dscDIOSetConfig(short board, IntPtr
config_bytes);
[...]
short board; //Handle of the Digital I/O board to operate
int[] config_bytes = new int[2];
[...]
result = dscDIOSetConfig(board, config_bytes);

Well, the reason for the error is clear: You are passing an array of
ints where an IntPtr is expected instead.

The remedy is not simple. It is not enough to take the address of the
array and pass it as a pointer, because the array is a managed object and it
could be moved around, which would cause a lot of trouble when the unmanaged
code attempted to access data at the original address which you passed in
the pointer. You have to allocate a fixed block of memory and "pin" it, so
that it won't move around. One way to do it is the following:


GCHandle pinnedRawData = GCHandle.Alloc(config_bytes, GCHandleType.Pinned);
IntPtr pinnedRawDataPtr = pinnedRawData.AddrOfPinnedObject();

result = dscDIOSetConfig(board, pinnedRawDataPtr);

pinnedRawData.Free();
 
P

paul f

I am getting two errors when i try to call dscDIOSetConfig external
function:
Error 1 The best overloaded method match for
'dllimport.Program.dscDIOSetConfig(short, System.IntPtr)' has some
invalid arguments C:\YB\dllimport\dllimport\Program.cs 25 21 dllimport
Error 2 Argument '2': cannot convert from 'int[]' to 'System.IntPtr' C:
\YB\dllimport\dllimport\Program.cs 25 44 dllimport
 [...]
       public static extern byte dscDIOSetConfig(short board, IntPtr
config_bytes);
[...]
          short board; //Handle of the Digital I/O board to operate
          int[] config_bytes = new int[2];
[...]
          result = dscDIOSetConfig(board, config_bytes);

    Well, the reason for the error is clear: You are passing an arrayof
ints where an IntPtr is expected instead.

    The remedy is not simple. It is not enough to take the address ofthe
array and pass it as a pointer, because the array is a managed object andit
could be moved around, which would cause a lot of trouble when the unmanaged
code attempted to access data at the original address which you passed in
the pointer. You have to allocate a fixed block of memory and "pin" it, so
that it won't move around. One way to do it is the following:

GCHandle pinnedRawData = GCHandle.Alloc(config_bytes, GCHandleType.Pinned);
IntPtr pinnedRawDataPtr = pinnedRawData.AddrOfPinnedObject();

result = dscDIOSetConfig(board, pinnedRawDataPtr);

pinnedRawData.Free();

Hi Alberto,
This worked!
thank you for your help!!! much appreciated
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top