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;
}

Reply via email to