[Interop] Marshal of void**

  • Thread starter laurent couraud
  • Start date
L

laurent couraud

Hi,



First, sorry if this is not the right place to ask this question.



I have a DLL in C which contains a function with the signature:



void Init(void** href);



It is supposed to be used like this in C



void* href = NULL;

Init( &href); // the library do some memory allocation there and then set
the value of href.

// Then i must provide this href variable to all others function of the dll.

ApiFunc1(href, .);

ApiFunc2(href, .);



As you guess I want to call this DLL from CSharp. How to do it?



Thank in advance for any hint.



Best regards.
 
A

Arne Vajhøj

I have a DLL in C which contains a function with the signature:

void Init(void** href);

It is supposed to be used like this in C

void* href = NULL;
Init( &href); // the library do some memory allocation there and then set
the value of href.
// Then i must provide this href variable to all others function of the dll.
ApiFunc1(href, .);
ApiFunc2(href, .);

As you guess I want to call this DLL from CSharp. How to do it?

Example that seems to work here:

#include <stdio.h>
#include <string.h>

__declspec(dllexport) void init(void **h)
{
char *s = (char*)malloc(100);
strcpy(s, "Hello world!");
*h = s;
}

__declspec(dllexport) void print(void *h)
{
printf("%s\r\n", (char*)h);
}

using System;
using System.Runtime.InteropServices;

namespace E
{
public class Program
{
[DllImport(@"C:\work\rpp.dll")]
public extern static void init(out IntPtr h);
[DllImport(@"C:\work\rpp.dll")]
public extern static void print(IntPtr h);
public static void Main(string[] args)
{
IntPtr h;
init(out h);
print(h);
Console.ReadKey();
}
}
}

Arne
 
L

laurent couraud

Arne Vajhøj said:
I have a DLL in C which contains a function with the signature:

void Init(void** href);

It is supposed to be used like this in C

void* href = NULL;
Init( &href); // the library do some memory allocation there and then set
the value of href.
// Then i must provide this href variable to all others function of the
dll.
ApiFunc1(href, .);
ApiFunc2(href, .);

As you guess I want to call this DLL from CSharp. How to do it?

Example that seems to work here:

#include <stdio.h>
#include <string.h>

__declspec(dllexport) void init(void **h)
{
char *s = (char*)malloc(100);
strcpy(s, "Hello world!");
*h = s;
}

__declspec(dllexport) void print(void *h)
{
printf("%s\r\n", (char*)h);
}

using System;
using System.Runtime.InteropServices;

namespace E
{
public class Program
{
[DllImport(@"C:\work\rpp.dll")]
public extern static void init(out IntPtr h);
[DllImport(@"C:\work\rpp.dll")]
public extern static void print(IntPtr h);
public static void Main(string[] args)
{
IntPtr h;
init(out h);
print(h);
Console.ReadKey();
}
}
}

Arne

Thank,



But in fact I forget to mention than my variable href is a field of a class.

In fact I tried already something similar (I think it is similar) than what
you suggest.

-------------------------------------------

using System;

using System.Runtime.InteropServices;



internal Class NativeAPI{

[DllImport(.)]

public extern static void Init(void** href);

[DllImport(.)]

public extern static void Print(void* href);

}





internal Class MyClass{



private void* href = null;



public void Init(){

unsafe{

fixed(void** ptr = &href){

NativeAPI.Init(ptr);

}

}

}



public void Print(){

NativeAPI.Print(href);

}

}

---------------------------------------------------



It works well at the beginning but after some call to Print method it stop
to work.

I suspect I need to pin the variable. I suppose for this I must use GChandle
or HandleRef but I don't understand how to use them for now. And the other
point is that I read on MSDN than pinning slow down the garbage collector.

Then maybe I must use allocation on unmanaged side with
Marshal.AllocHGlobal() but I didn't win to do so until now.
 
A

Arne Vajhøj

Arne Vajhøj said:
I have a DLL in C which contains a function with the signature:

void Init(void** href);

It is supposed to be used like this in C

void* href = NULL;
Init( &href); // the library do some memory allocation there and then set
the value of href.
// Then i must provide this href variable to all others function of the
dll.
ApiFunc1(href, .);
ApiFunc2(href, .);

As you guess I want to call this DLL from CSharp. How to do it?

Example that seems to work here:

#include <stdio.h>
#include <string.h>

__declspec(dllexport) void init(void **h)
{
char *s = (char*)malloc(100);
strcpy(s, "Hello world!");
*h = s;
}

__declspec(dllexport) void print(void *h)
{
printf("%s\r\n", (char*)h);
}

using System;
using System.Runtime.InteropServices;

namespace E
{
public class Program
{
[DllImport(@"C:\work\rpp.dll")]
public extern static void init(out IntPtr h);
[DllImport(@"C:\work\rpp.dll")]
public extern static void print(IntPtr h);
public static void Main(string[] args)
{
IntPtr h;
init(out h);
print(h);
Console.ReadKey();
}
}
}
But in fact I forget to mention than my variable href is a field of a class.

That should not matter.
In fact I tried already something similar (I think it is similar) than what
you suggest.

-------------------------------------------

using System;

using System.Runtime.InteropServices;



internal Class NativeAPI{

[DllImport(.)]

public extern static void Init(void** href);

[DllImport(.)]

public extern static void Print(void* href);

}





internal Class MyClass{



private void* href = null;



public void Init(){

unsafe{

fixed(void** ptr = &href){

NativeAPI.Init(ptr);

}

}

}



public void Print(){

NativeAPI.Print(href);

}

}

---------------------------------------------------



It works well at the beginning but after some call to Print method it stop
to work.

That seems a lot more complex than what I was suggesting.

Did you try IntPtr and out?

Arne
 

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