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
--
-----------------------------------------------------------------
[EMAIL PROTECTED] debian/rules
[EMAIL PROTECTED] Monkeys do it better
_______________________________________________
Mono-list maillist - [EMAIL PROTECTED]
http://lists.ximian.com/mailman/listinfo/mono-list
// call the native function...
using System;
using System.Text;
using System.Runtime.InteropServices;
public class managed {
[DllImport("native")]
private static extern int wgetname(
[Out, MarshalAs(UnmanagedType.LPWStr)]
StringBuilder sb,
uint n);
[DllImport("native")]
private static extern int getname(StringBuilder sb, uint n);
public static void Main () {
StringBuilder sb = new StringBuilder (255);
getname(sb, (uint) sb.Capacity);
Console.WriteLine("name: `{0}'", sb);
sb = new StringBuilder(1024);
wgetname(sb, (uint) sb.Capacity);
Console.WriteLine("wide name: `{0}'", sb);
}
}
/*
* Native DLL.
*/
#include <string.h>
#include <stdio.h>
#ifdef _MSC_VER
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
EXPORT
int
wgetname(__wchar_t* s, unsigned int n)
{
const wchar_t m[] = L"This is my message. Isn't it nifty?";
printf("Inside wgetname; n=%i\n", n);
wcsncpy(s, m, n);
return 0;
}
EXPORT
int
getname(char* s, unsigned int n)
{
const char m[] = "This is my message. Isn't it nifty?";
printf("Inside getname; n=%i\n", n);
strncpy(s, m, n);
return 0;
}