Sign in to follow this  
alexbOrsova

Type Marshaling when using a C++ dll in C#

Recommended Posts

alexbOrsova    122
Hello. I need some help with type marshaling in C#. I'm trying to use the ESCAPI 2.0 dll, which was written in C++, in a C# class. The dll is available at http://sol.gfxile.net/zip/escapi21.zip. There are example escapi.h and escapi.cpp files there for using this dll from C++. I've tried to convert this into C#, however I don't know how to setup a pointer to a C# struct. In the example files the struct is called SimpleCapParams and in my code it's named CapParams. The code I have right now in C# compiles and runs but it doesn't actually capture a picture because the mTargetBuf array is empty and I'm sure this is because I haven't set it up right with Marshaling (and because the initCapture method returns a one for success). Can anyone tell me what I'm doing wrong? Here's my C# code so far: using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace RobotServer { class CameraManager { [StructLayout(LayoutKind.Sequential)] struct CapParams { [MarshalAs(UnmanagedType.SafeArray)] public int[] mTargetBuf; public int mHeight; public int mWidth; } [DllImport("escapi.dll")] private static extern int countCaptureDevices(); [DllImport("escapi.dll")] private static extern int initCapture(uint deviceno, CapParams capParams); [DllImport("escapi.dll")] private static extern void deinitCapture(uint deviceno); [DllImport("escapi.dll")] private static extern void doCapture(uint deviceno); [DllImport("escapi.dll")] private static extern int isCaptureDone(uint deviceno); [DllImport("escapi.dll")] private static extern void getCaptureDeviceName(uint deviceno, [MarshalAs(UnmanagedType.LPStr)] string devicename, int bufferLength); public static void Main(String[] args) { CameraManager cm = new CameraManager(); } public CameraManager() { //let's test this CapParams cparamsTest = new CapParams(); cparamsTest.mHeight = 100; cparamsTest.mWidth = 100; cparamsTest.mTargetBuf = new int[1000]; System.Console.WriteLine(countCaptureDevices()); System.Console.WriteLine(initCapture(0, cparamsTest)); doCapture(0); while(isCaptureDone(0) <= 0) { } deinitCapture(0); for(int x = 0; x < 1000; x++) { System.Console.Write(cparamsTest.mTargetBuf[x] + " "); } System.Console.WriteLine("Done"); System.Console.ReadLine(); } } }

Share this post


Link to post
Share on other sites
alexbOrsova    122
Thanks. I fixed that. Unfortunately, it still doesn't work. I'm convinced I'm doing something wrong with type marshaling. Here's my updated code:

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

namespace RobotServer
{
class CameraManager
{
[StructLayout(LayoutKind.Sequential)]
struct CapParams
{
[MarshalAs(UnmanagedType.SafeArray)]
public int[] mTargetBuf;

public int mHeight;
public int mWidth;
}

[DllImport("escapi.dll", EntryPoint = "countCaptureDevices")]
private static extern int countCaptureDevices();

[DllImport("escapi.dll", EntryPoint = "initCapture")]
private static extern int initCapture(uint deviceno, CapParams capParams);

[DllImport("escapi.dll", EntryPoint = "deinitCapture")]
private static extern void deinitCapture(uint deviceno);

[DllImport("escapi.dll", EntryPoint = "doCapture")]
private static extern void doCapture(uint deviceno);

[DllImport("escapi.dll", EntryPoint = "isCaptureDone")]
private static extern int isCaptureDone(uint deviceno);

[DllImport("escapi.dll", EntryPoint = "getCaptureDeviceName")]
private static extern void getCaptureDeviceName(uint deviceno, [MarshalAs(UnmanagedType.LPStr)] string devicename, int bufferLength);

public static void Main(String[] args)
{
CameraManager cm = new CameraManager();
}

public CameraManager()
{
//let's test this
CapParams cparamsTest = new CapParams();

cparamsTest.mHeight = 100;
cparamsTest.mWidth = 100;
cparamsTest.mTargetBuf = new int[1000];

System.Console.WriteLine(countCaptureDevices());

System.Console.WriteLine(initCapture(0, cparamsTest));

doCapture(0);

while(isCaptureDone(0) <= 0) { }

deinitCapture(0);

for(int x = 0; x < 1000; x++)
{
System.Console.Write(cparamsTest.mTargetBuf[x] + " ");
}

System.Console.WriteLine("Done");

System.Console.ReadLine();
}
}
}

Share this post


Link to post
Share on other sites
mutex    1111
Marshalling CapParams.mTargetBuf as UnmanagedType.SafeArray is incorrect. SafeArray corresponds to the unmanaged SAFEARRAY, which is a particular structure that describes arrays.

Have you tried LPArray instead?

[StructLayout(LayoutKind.Sequential)]
struct CapParams
{
[MarshalAs(UnmanagedType.LPArray)]
public int[] mTargetBuf;

public int mHeight;
public int mWidth;
};

Share this post


Link to post
Share on other sites
alexbOrsova    122
I'm looking into that wizard right now. I tried changing the SafeArray to LPArray and now it gets a runtime error "
Cannot marshal field 'mTargetBuf' of type 'CapParams': Invalid managed/unmanaged type combination (Arrays fields must be paired with ByValArray or SafeArray)".

If the wizard works, that's great. However, If I don't understand how to do it manually I'm dependent on the software and I really don't want to shell out the cash to buy it right now.

[edit]
Btw, the PInvoke Wizard doesn't run on my computer because I don't have .NET Framework 1.1. I have .NET Framework 2.0 installed but it doesn't seem to be compatible with that. If you have it installed, do you think you could run my .h header file through it?
[/edit]

Thanks for taking the time to respond. --Alex

Share this post


Link to post
Share on other sites
JamesLewis    234
Hey, you should be able to grab yourself a copy .Net 1.1. Have a look around and see what you find. Failing that, PM me and I'll have a look at the .h file for you.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this