[Mono-list] DllImport ... help
Jonathan Pryor
jonpryor@vt.edu
18 Jun 2002 21:39:26 -0400
--=-VoRnMN5LkZQuyrecl6qh
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
What happens if `getname' takes `wchar_t*'? An
`IndexOutOfBoundsException'!
The exception is due to two things:
- .NET appears to marshal as `char' by default, not `wchar_t'
- Because of the above, `wcsncpy' (the logical equivalent to
`strncpy') winds up copying *way* past the buffer that .NET
allocates.
Marshaling is particularly apparent, because if you make the passed
capacity sufficiently small enough that you can *ensure* you won't
over-write your bounds:
getname(sb, sb.Capacity/8);
when you write it you'll only get the first character of the passed
string. Try it. It's very enlightening.
The fix is to attach a `MarshalAs' attribute, specifying that a
wide-character string should be marshalled.
[DllImport("native")]
private static extern int wgetname(
[Out, MarshalAs(UnmanagedType.LPWStr)]
StringBuilder sb,
uint n);
See the attached example files.
- Jon
On Mon, 2002-06-17 at 14:05, Paolo Molaro wrote:
On 06/15/02 Jonathan Pryor wrote:
> For example, the following works with .NET
>
> // native.c
> // Native library
> #include <string.h>
>
> #ifdef _MSC_VER
> __declspec(dllexport)
> #endif
> int getname(char* s, unsigned int n)
> {
> const char m[] = "This is my message. Isn't it nice?";
> strncpy(s, m, n);
> return 0;
> }
[...]
> public class ghbn {
> [DllImport("native")]
> private static extern int getname(
> StringBuilder sb,
> uint len);
What happens if getname() takes a wchar_t? Do you have to specify
additional information in a MarshalAs attribute?
BTW, if anyone can find the documentation that the class docs calls
"Data Marshaling Specification" I'll be grateful.
lupus
--
-----------------------------------------------------------------
lupus@debian.org debian/rules
lupus@ximian.com Monkeys do it better
_______________________________________________
Mono-list maillist - Mono-list@ximian.com
http://lists.ximian.com/mailman/listinfo/mono-list
--=-VoRnMN5LkZQuyrecl6qh
Content-Disposition: attachment; filename=managed.cs
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; name=managed.cs; charset=UTF-8
// call the native function...=0D
=0D
using System;=0D
using System.Text;=0D
using System.Runtime.InteropServices;=0D
=0D
public class managed {=0D
[DllImport("native")]=0D
private static extern int wgetname(=0D
[Out, MarshalAs(UnmanagedType.LPWStr)]=0D
StringBuilder sb,=20=0D
uint n);=0D
=0D
[DllImport("native")]=0D
private static extern int getname(StringBuilder sb, uint n);=0D
=0D
public static void Main () {=0D
StringBuilder sb =3D new StringBuilder (255);=0D
getname(sb, (uint) sb.Capacity);=0D
Console.WriteLine("name: `{0}'", sb);=0D
=0D
sb =3D new StringBuilder(1024);=0D
=0D
wgetname(sb, (uint) sb.Capacity);=0D
Console.WriteLine("wide name: `{0}'", sb);=0D
}=0D
}=0D
=0D
--=-VoRnMN5LkZQuyrecl6qh
Content-Disposition: attachment; filename=native.c
Content-Transfer-Encoding: quoted-printable
Content-Type: text/x-c; name=native.c; charset=UTF-8
/*=0D
* Native DLL.=0D
*/=0D
#include <string.h>=0D
#include <stdio.h>=0D
=0D
#ifdef _MSC_VER=0D
#define EXPORT __declspec(dllexport)=0D
#else=0D
#define EXPORT=0D
#endif=0D
=0D
EXPORT=0D
int=0D
wgetname(__wchar_t* s, unsigned int n)=0D
{=0D
const wchar_t m[] =3D L"This is my message. Isn't it nifty?";=0D
printf("Inside wgetname; n=3D%i\n", n);=0D
wcsncpy(s, m, n);=0D
return 0;=0D
}=0D
=0D
EXPORT=0D
int=0D
getname(char* s, unsigned int n)=0D
{=0D
const char m[] =3D "This is my message. Isn't it nifty?";=0D
printf("Inside getname; n=3D%i\n", n);=0D
strncpy(s, m, n);=0D
return 0;=0D
}=0D
=0D
--=-VoRnMN5LkZQuyrecl6qh--