Managed C# to unmanaged DLL

N

nachiketamishra

Hi,
I have a to pass a char* from C# to a library in C++. I have tried
passing string and doing [MarshaAs(UnmanagedType.LPStr)]string myVal
and it didn't work . I also tried to pass an unsafe call by declaring
my method as unsafe and passing a pointer and it still doesn't work.

Any help will be appreciated.

Regards,
Nach

Code:

[DllImport(StreamLibPath)]
unsafe static extern uint writeStream(int handle, char* pBuf, uint
size, uint actualWrittenSize);


unsafe public void callStream()
{
char* data
writeStream(_myHandle, data, writeSize, writtenSize));
}
 
W

Willy Denoyette [MVP]

Hi,
I have a to pass a char* from C# to a library in C++. I have tried
passing string and doing [MarshaAs(UnmanagedType.LPStr)]string myVal
and it didn't work . I also tried to pass an unsafe call by declaring
my method as unsafe and passing a pointer and it still doesn't work.

Any help will be appreciated.

Regards,
Nach

Code:

[DllImport(StreamLibPath)]
unsafe static extern uint writeStream(int handle, char* pBuf, uint
size, uint actualWrittenSize);


unsafe public void callStream()
{
char* data
writeStream(_myHandle, data, writeSize, writtenSize));
}

Check what kind of character encoding is used by the API and apply the appropriate MarshalAs
attibute.
Note also that I'm quite sure that actualWrittenSize should be passed byref.

Here is the signature that passes the string as a Wide character string, actualWrittenSize
should contain the characters written after the call (I guess).
static extern uint writeStream(int handle, [MarshaAs(UnmanagedType.LPWStr)] string pBuf,
uint size, out uint actualWrittenSize);


Willy.
 
S

Selvin

Check what kind of character encoding is used by the API and apply the
appropriate MarshalAs attibute.
Note also that I'm quite sure that actualWrittenSize should be passed
byref.

Here is the signature that passes the string as a Wide character string,
actualWrittenSize should contain the characters written after the call (I
guess).
static extern uint writeStream(int handle,
[MarshaAs(UnmanagedType.LPWStr)] string pBuf, uint size, out uint
actualWrittenSize);

or if char* doesnt means string but byte array

static extern uint writeStream(int handle, IntPtr pBuf, uint size, ref uint
actualWrittenSize);

and use it like this

uint len = 70;
uint rlen = 0;
byte[] bytes = new byte[len];
//fill the bytes
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.Copy(bytes, 0, ptr, len);
writeStream(handle, ptr, len, ref rlen);
Marshal.FreeHGlobal(ptr);

pozdrawiam

Przemek Sulikowski
 
N

nachiketamishra

the signature of writeStream is

public uint writeStream(int handle, char* pBuf, uint length, uint*
actualWrittenLength)

Nach
 
N

nachiketamishra

in C++ it is

public unsigned int writeStream(int handle, char* pBuf, unsigned int
bufLen, unsigned int*
pWrittenLen)
 
B

Ben Voigt

Selvin said:
Check what kind of character encoding is used by the API and apply the
appropriate MarshalAs attibute.
Note also that I'm quite sure that actualWrittenSize should be passed
byref.

Here is the signature that passes the string as a Wide character string,
actualWrittenSize should contain the characters written after the call (I
guess).
static extern uint writeStream(int handle,
[MarshaAs(UnmanagedType.LPWStr)] string pBuf, uint size, out uint
actualWrittenSize);

or if char* doesnt means string but byte array

static extern uint writeStream(int handle, IntPtr pBuf, uint size, ref
uint actualWrittenSize);

and use it like this

uint len = 70;
uint rlen = 0;
byte[] bytes = new byte[len];
//fill the bytes
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.Copy(bytes, 0, ptr, len);
writeStream(handle, ptr, len, ref rlen);
Marshal.FreeHGlobal(ptr);

Wouldn't a pinning pointer be better for that?
 
N

nachiketamishra

Hi Willy,
Thanks a zillion. That worked.

Nach

Hi,
I have a to pass a char* from C# to a library in C++. I have tried
passing string and doing [MarshaAs(UnmanagedType.LPStr)]string myVal
and it didn't work . I also tried to pass an unsafe call by declaring
my method as unsafe and passing a pointer and it still doesn't work.
Any help will be appreciated.
Regards,
Nach

[DllImport(StreamLibPath)]
unsafe static extern uint writeStream(int handle, char* pBuf, uint
size, uint actualWrittenSize);
unsafe public void callStream()
{
char* data
writeStream(_myHandle, data, writeSize, writtenSize));
}Check what kind of character encoding is used by the API and apply the appropriate MarshalAs
attibute.
Note also that I'm quite sure that actualWrittenSize should be passed byref.

Here is the signature that passes the string as a Wide character string, actualWrittenSize
should contain the characters written after the call (I guess).
static extern uint writeStream(int handle, [MarshaAs(UnmanagedType.LPWStr)] string pBuf,
uint size, out uint actualWrittenSize);

Willy.- Hide quoted text -- Show quoted text -
 
W

Willy Denoyette [MVP]

Selvin said:
Check what kind of character encoding is used by the API and apply the appropriate
MarshalAs attibute.
Note also that I'm quite sure that actualWrittenSize should be passed byref.

Here is the signature that passes the string as a Wide character string,
actualWrittenSize should contain the characters written after the call (I guess).
static extern uint writeStream(int handle, [MarshaAs(UnmanagedType.LPWStr)] string pBuf,
uint size, out uint actualWrittenSize);

or if char* doesnt means string but byte array

static extern uint writeStream(int handle, IntPtr pBuf, uint size, ref uint
actualWrittenSize);

and use it like this

uint len = 70;
uint rlen = 0;
byte[] bytes = new byte[len];
//fill the bytes
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.Copy(bytes, 0, ptr, len);
writeStream(handle, ptr, len, ref rlen);
Marshal.FreeHGlobal(ptr);

pozdrawiam

Przemek Sulikowski


If it was a byte array, I would not marshal an array of bytes in code, this is done more
efficiently by the interop layer.

static extern uint writeStream(int handle, byte[] pBuf, ....);

byte[] bytes = new byte[len]
writeStream(handle, bytes, len, ref rlen);

Willy.
 
N

nachiketamishra

The C++ library doesn't take a byte array. It takes a Char*. So I am
not sure , if it will accept a byte array ?

nach

Check what kind of character encoding is used by the API and apply the appropriate
MarshalAs attibute.
Note also that I'm quite sure that actualWrittenSize should be passed byref.
Here is the signature that passes the string as a Wide character string,
actualWrittenSize should contain the characters written after the call (I guess).
static extern uint writeStream(int handle, [MarshaAs(UnmanagedType.LPWStr)] string pBuf,
uint size, out uint actualWrittenSize);
or if char* doesnt means string but byte array
static extern uint writeStream(int handle, IntPtr pBuf, uint size, ref uint
actualWrittenSize);
and use it like this
uint len = 70;
uint rlen = 0;
byte[] bytes = new byte[len];
//fill the bytes
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.Copy(bytes, 0, ptr, len);
writeStream(handle, ptr, len, ref rlen);
Marshal.FreeHGlobal(ptr);
pozdrawiam

Przemek SulikowskiIf it was a byte array, I would not marshal an array of bytes in code, this is done more
efficiently by the interop layer.

static extern uint writeStream(int handle, byte[] pBuf, ....);

byte[] bytes = new byte[len]
writeStream(handle, bytes, len, ref rlen);

Willy.- Hide quoted text -- Show quoted text -
 
N

nachiketamishra

How will a pinning pointer help me ?

Check what kind of character encoding is used by the API and apply the
appropriate MarshalAs attibute.
Note also that I'm quite sure that actualWrittenSize should be passed
byref.
Here is the signature that passes the string as a Wide character string,
actualWrittenSize should contain the characters written after the call (I
guess).
static extern uint writeStream(int handle,
[MarshaAs(UnmanagedType.LPWStr)] string pBuf, uint size, out uint
actualWrittenSize);
or if char* doesnt means string but byte array
static extern uint writeStream(int handle, IntPtr pBuf, uint size, ref
uint actualWrittenSize);
and use it like this
uint len = 70;
uint rlen = 0;
byte[] bytes = new byte[len];
//fill the bytes
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.Copy(bytes, 0, ptr, len);
writeStream(handle, ptr, len, ref rlen);
Marshal.FreeHGlobal(ptr);Wouldn't a pinning pointer be better for that?



pozdrawiam

Przemek Sulikowski- Hide quoted text -- Show quoted text -- Hide quoted text -- Show quoted text -
 
W

Willy Denoyette [MVP]

The C++ library doesn't take a byte array. It takes a Char*. So I am
not sure , if it will accept a byte array ?

Please note that I was not suggesting you to pass a byte[], I was only replying to Selvin
who said "....or if char* doesn't means string but byte array..."
Passing a byte[] will work, as long as char* is a pointer to an array of char (8bit entity).
Following illustrates my point, but again don't use this to pass "character string" data.

//C++
#include <cstdio>
extern "C" void __declspec(dllexport) __stdcall Foo(char* byte)
{
printf_s(byte);
}

//C#
[DllImport("somedll")]
private static extern bool Foo(byte[] bytes);
....
byte[] b = new byte[5] { 49, 50, 51, 52, 00 };
Foo(b);

Willy.
 

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