Dynamic Invokes and Marshaling a "ref SByte*"

  • Thread starter Stephen Gennard
  • Start date
S

Stephen Gennard

Hello,

I having a problem dynamically invoking a static method that takes a
reference to a SByte*. If I do it directly it works just fine.

Anyone any ideas why?

I have include a example below...

--
Stephen Gennard
email: (e-mail address removed)

D:\development>csc /unsafe /target:library /out:sb.dll sb.cs

Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.


D:\development\netx45\ilrts\Tests>csc /unsafe /define:DYNAMIC sbinvoke.cs
Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.


D:\development>sbinvoke
DYNAMIC invoke of GetMemory()

Unhandled Exception: System.ArgumentException: Object type cannot be
converted t
o target type.
at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj,
BindingFlag
s invokeAttr, Binder binder, Object[] parameters, CultureInfo culture,
Boolean i
sBinderDefault, Assembly caller, Boolean verifyAccess)
at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj,
BindingFlag
s invokeAttr, Binder binder, Object[] parameters, CultureInfo culture,
Boolean v
erifyAccess)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture)
at SBInvoke.test()
at SBInvoke.Main(String[] args)


Now for the one that works...

D:\development> csc /unsafe sbinvoke.cs /r:sb.dll
Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.


D:\development>sbinvoke
ILREF invoke of GetMemory()

abcdefghijklmnopqrstuvwxyz

--file: SBInvoke.cs
using System;
using System.Runtime.InteropServices;
using System.Reflection;

public class SBInvoke
{
public unsafe static void test()
{
SByte *memory = null;
#if DYNAMIC
Console.WriteLine("DYNAMIC invoke of GetMemory()");

Assembly assembly = Assembly.LoadFrom("sb.dll");
Type type = assembly.GetType("SB");

/* find GetMemory() method */
MethodInfo method2invoke = null;
foreach (MethodInfo method in type.GetMethods())
{
if (method.Name.CompareTo("GetMemory") == 0)
method2invoke = method;
}

object[] parms = { (IntPtr)memory };

int size = (int)method2invoke.Invoke(method2invoke,parms);

byte *countPtr = (byte*)(IntPtr)parms[0];
#else
Console.WriteLine("ILREF invoke of GetMemory()");

int size = SB.GetMemory(ref memory);
byte *countPtr = (byte*)memory;
#endif

Console.WriteLine();

for(int c=0; c<size; c++)
{
Console.Write((char)*countPtr);
countPtr++;
}

Console.WriteLine();
}

public static int Main(string[] args)
{
test();
return 0;
}
}

--file: sb.cs
using System.Runtime.InteropServices;
using System;

public class SB
{
public unsafe static int GetMemory(
#if DOES_AN_ATTRIBUTE_OR_TWO_HELP
[MarshalAs(UnmanagedType.LPArray)]
#endif
ref SByte *ptr)
{
ptr = (SByte*)Marshal.AllocHGlobal(26);

byte *initPtr = (byte*)ptr;
for(int c=0; c<26; c++)
*initPtr++=(byte)('a'+(byte)c);

return 26;
}
}



using System.Runtime.InteropServices;
using System;

public class SB
{
public unsafe static int GetMemory(
#if DOES_AN_ATTRIBUTE_OR_TWO_HELP
[MarshalAs(UnmanagedType.LPArray)]
#endif
ref SByte *ptr)
{
ptr = (SByte*)Marshal.AllocHGlobal(26);

byte *initPtr = (byte*)ptr;
for(int c=0; c<26; c++)
*initPtr++=(byte)('a'+(byte)c);

return 26;
}
}


using System;
using System.Runtime.InteropServices;
using System.Reflection;

public class SBInvoke
{
public unsafe static void test()
{
SByte *memory = null;
#if DYNAMIC
Console.WriteLine("DYNAMIC invoke of GetMemory()");

Assembly assembly = Assembly.LoadFrom("sb.dll");
Type type = assembly.GetType("SB");

/* find GetMemory() method */
MethodInfo method2invoke = null;
foreach (MethodInfo method in type.GetMethods())
{
if (method.Name.CompareTo("GetMemory") == 0)
method2invoke = method;
}

object[] parms = { (IntPtr)memory };

int size = (int)method2invoke.Invoke(method2invoke,parms);

byte *countPtr = (byte*)(IntPtr)parms[0];
#else
Console.WriteLine("ILREF invoke of GetMemory()");

int size = SB.GetMemory(ref memory);
byte *countPtr = (byte*)memory;
#endif

Console.WriteLine();

for(int c=0; c<size; c++)
{
Console.Write((char)*countPtr);
countPtr++;
}

Console.WriteLine();
}

public static int Main(string[] args)
{
test();
return 0;
}
}
 
J

Jeffrey Tan[MSFT]

Hi Stephen,

I believe the problem lies in here:
The GetMemory() function in your dll must be pass the SByte* parameter.
This can be done in normal invoke by:
int size = SB.GetMemory(ref memory);

But in dynamic invoke, the parameter must be passed through Objects array
which can not
contain pointer. You convert SByte * to IntPtr and pass it to GetMemory().
IntPtr dose not
match SByte parameter, so “Object type cannot be converted to target type”
exception arose.

My suggestion is changing the parameter type that must be passed to
GetMemory to IntPtr and convert it to
SByte* in GetMemory(). Then all will be ok.

My source code is listed below:

sbinvoke.cs

#define DYNAMIC
using System;
using System.Runtime.InteropServices;
using System.Reflection;

public class SBInvoke
{
public unsafe static void test()
{
try
{
SByte *p=null;
IntPtr memory=new IntPtr (p);
#if DYNAMIC
Console.WriteLine("DYNAMIC invoke of GetMemory()");

Assembly assembly = Assembly.LoadFrom("sb.dll");
Type type = assembly.GetType("SB");

/* find GetMemory() method */
MethodInfo method2invoke = null;
foreach (MethodInfo method in type.GetMethods())
{
if (method.Name.CompareTo("GetMemory") == 0)
method2invoke = method;
}

object[] parms =new object [1];
parms[0]=memory;

int size = (int)method2invoke.Invoke(method2invoke,parms);

byte *countPtr = (byte*)(IntPtr)parms[0];
#else
Console.WriteLine("ILREF invoke of GetMemory()");

int size = SB.GetMemory(ref memory);
byte *countPtr = (byte*)memory;
#endif


Console.WriteLine();

for(int c=0; c<size; c++)
{
Console.Write((char)*countPtr);
countPtr++;
}

Console.WriteLine();
}
catch(Exception e)
{
Console.WriteLine("Exception:"+e.Message);
}
Console.Read ();
}

public static int Main(string[] args)
{
test();
return 0;
}
}

sb.cs

using System.Runtime.InteropServices;
using System;

public class SB
{
public unsafe static int GetMemory(
#if DOES_AN_ATTRIBUTE_OR_TWO_HELP
[MarshalAs(UnmanagedType.LPArray)]
#endif
ref IntPtr m)
{
SByte *ptr=(SByte *)m;
ptr = (SByte*)Marshal.AllocHGlobal(26);
m=(IntPtr)ptr;

byte *initPtr = (byte*)ptr;
for(int c=0; c<26; c++)
*initPtr++=(byte)('a'+(byte)c);

return 26;
}
}

This code worked well on my machine.
Hope this helps.


Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Message-ID: <[email protected]>
| Date: Fri, 01 Aug 2003 11:36:28 +0100
| From: Stephen Gennard <[email protected]>
| User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5b)
Gecko/20030723 Thunderbird/0.1
| X-Accept-Language: en-us, en
| MIME-Version: 1.0
| Subject: Dynamic Invokes and Marshaling a "ref SByte*"
| Content-Type: multipart/mixed;
| boundary="------------090005080707020102090809"
| Newsgroups: microsoft.public.dotnet.languages.csharp
| NNTP-Posting-Host: pix094.mfltd.co.uk 193.129.81.94
| Lines: 1
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!tk2msftngp13.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:173504
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| Hello,
|
| I having a problem dynamically invoking a static method that takes a
| reference to a SByte*. If I do it directly it works just fine.
|
| Anyone any ideas why?
|
| I have include a example below...
|
| --
| Stephen Gennard
| email: (e-mail address removed)
|
| D:\development>csc /unsafe /target:library /out:sb.dll sb.cs
|
| Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
| for Microsoft (R) .NET Framework version 1.1.4322
| Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
|
|
| D:\development\netx45\ilrts\Tests>csc /unsafe /define:DYNAMIC sbinvoke.cs
| Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
| for Microsoft (R) .NET Framework version 1.1.4322
| Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
|
|
| D:\development>sbinvoke
| DYNAMIC invoke of GetMemory()
|
| Unhandled Exception: System.ArgumentException: Object type cannot be
| converted t
| o target type.
| at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj,
| BindingFlag
| s invokeAttr, Binder binder, Object[] parameters, CultureInfo culture,
| Boolean i
| sBinderDefault, Assembly caller, Boolean verifyAccess)
| at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj,
| BindingFlag
| s invokeAttr, Binder binder, Object[] parameters, CultureInfo culture,
| Boolean v
| erifyAccess)
| at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
| BindingFlags invoke
| Attr, Binder binder, Object[] parameters, CultureInfo culture)
| at SBInvoke.test()
| at SBInvoke.Main(String[] args)
|
|
| Now for the one that works...
|
| D:\development> csc /unsafe sbinvoke.cs /r:sb.dll
| Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
| for Microsoft (R) .NET Framework version 1.1.4322
| Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
|
|
| D:\development>sbinvoke
| ILREF invoke of GetMemory()
|
| abcdefghijklmnopqrstuvwxyz
|
| --file: SBInvoke.cs
| using System;
| using System.Runtime.InteropServices;
| using System.Reflection;
|
| public class SBInvoke
| {
| public unsafe static void test()
| {
| SByte *memory = null;
| #if DYNAMIC
| Console.WriteLine("DYNAMIC invoke of GetMemory()");
|
| Assembly assembly = Assembly.LoadFrom("sb.dll");
| Type type = assembly.GetType("SB");
|
| /* find GetMemory() method */
| MethodInfo method2invoke = null;
| foreach (MethodInfo method in type.GetMethods())
| {
| if (method.Name.CompareTo("GetMemory") == 0)
| method2invoke = method;
| }
|
| object[] parms = { (IntPtr)memory };
|
| int size = (int)method2invoke.Invoke(method2invoke,parms);
|
| byte *countPtr = (byte*)(IntPtr)parms[0];
| #else
| Console.WriteLine("ILREF invoke of GetMemory()");
|
| int size = SB.GetMemory(ref memory);
| byte *countPtr = (byte*)memory;
| #endif
|
| Console.WriteLine();
|
| for(int c=0; c<size; c++)
| {
| Console.Write((char)*countPtr);
| countPtr++;
| }
|
| Console.WriteLine();
| }
|
| public static int Main(string[] args)
| {
| test();
| return 0;
| }
| }
|
| --file: sb.cs
| using System.Runtime.InteropServices;
| using System;
|
| public class SB
| {
| public unsafe static int GetMemory(
| #if DOES_AN_ATTRIBUTE_OR_TWO_HELP
| [MarshalAs(UnmanagedType.LPArray)]
| #endif
| ref SByte *ptr)
| {
| ptr = (SByte*)Marshal.AllocHGlobal(26);
|
| byte *initPtr = (byte*)ptr;
| for(int c=0; c<26; c++)
| *initPtr++=(byte)('a'+(byte)c);
|
| return 26;
| }
| }
|
|
|
|
 
S

Stephen Gennard

Thanks that works a treat.
Hi Stephen,

I believe the problem lies in here:
The GetMemory() function in your dll must be pass the SByte* parameter.
This can be done in normal invoke by:
int size = SB.GetMemory(ref memory);

But in dynamic invoke, the parameter must be passed through Objects array
which can not
contain pointer. You convert SByte * to IntPtr and pass it to GetMemory().
IntPtr dose not
match SByte parameter, so “Object type cannot be converted to target type”
exception arose.

My suggestion is changing the parameter type that must be passed to
GetMemory to IntPtr and convert it to
SByte* in GetMemory(). Then all will be ok.

My source code is listed below:

sbinvoke.cs

#define DYNAMIC
using System;
using System.Runtime.InteropServices;
using System.Reflection;

public class SBInvoke
{
public unsafe static void test()
{
try
{
SByte *p=null;
IntPtr memory=new IntPtr (p);
#if DYNAMIC
Console.WriteLine("DYNAMIC invoke of GetMemory()");

Assembly assembly = Assembly.LoadFrom("sb.dll");
Type type = assembly.GetType("SB");

/* find GetMemory() method */
MethodInfo method2invoke = null;
foreach (MethodInfo method in type.GetMethods())
{
if (method.Name.CompareTo("GetMemory") == 0)
method2invoke = method;
}

object[] parms =new object [1];
parms[0]=memory;

int size = (int)method2invoke.Invoke(method2invoke,parms);

byte *countPtr = (byte*)(IntPtr)parms[0];
#else
Console.WriteLine("ILREF invoke of GetMemory()");

int size = SB.GetMemory(ref memory);
byte *countPtr = (byte*)memory;
#endif


Console.WriteLine();

for(int c=0; c<size; c++)
{
Console.Write((char)*countPtr);
countPtr++;
}

Console.WriteLine();
}
catch(Exception e)
{
Console.WriteLine("Exception:"+e.Message);
}
Console.Read ();
}

public static int Main(string[] args)
{
test();
return 0;
}
}

sb.cs

using System.Runtime.InteropServices;
using System;

public class SB
{
public unsafe static int GetMemory(
#if DOES_AN_ATTRIBUTE_OR_TWO_HELP
[MarshalAs(UnmanagedType.LPArray)]
#endif
ref IntPtr m)
{
SByte *ptr=(SByte *)m;
ptr = (SByte*)Marshal.AllocHGlobal(26);
m=(IntPtr)ptr;

byte *initPtr = (byte*)ptr;
for(int c=0; c<26; c++)
*initPtr++=(byte)('a'+(byte)c);

return 26;
}
}

This code worked well on my machine.
Hope this helps.


Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Message-ID: <[email protected]>
| Date: Fri, 01 Aug 2003 11:36:28 +0100
| From: Stephen Gennard <[email protected]>
| User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5b)
Gecko/20030723 Thunderbird/0.1
| X-Accept-Language: en-us, en
| MIME-Version: 1.0
| Subject: Dynamic Invokes and Marshaling a "ref SByte*"
| Content-Type: multipart/mixed;
| boundary="------------090005080707020102090809"
| Newsgroups: microsoft.public.dotnet.languages.csharp
| NNTP-Posting-Host: pix094.mfltd.co.uk 193.129.81.94
| Lines: 1
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!tk2msftngp13.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:173504
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| Hello,
|
| I having a problem dynamically invoking a static method that takes a
| reference to a SByte*. If I do it directly it works just fine.
|
| Anyone any ideas why?
|
| I have include a example below...
|
| --
| Stephen Gennard
| email: (e-mail address removed)
|
| D:\development>csc /unsafe /target:library /out:sb.dll sb.cs
|
| Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
| for Microsoft (R) .NET Framework version 1.1.4322
| Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
|
|
| D:\development\netx45\ilrts\Tests>csc /unsafe /define:DYNAMIC sbinvoke.cs
| Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
| for Microsoft (R) .NET Framework version 1.1.4322
| Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
|
|
| D:\development>sbinvoke
| DYNAMIC invoke of GetMemory()
|
| Unhandled Exception: System.ArgumentException: Object type cannot be
| converted t
| o target type.
| at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj,
| BindingFlag
| s invokeAttr, Binder binder, Object[] parameters, CultureInfo culture,
| Boolean i
| sBinderDefault, Assembly caller, Boolean verifyAccess)
| at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj,
| BindingFlag
| s invokeAttr, Binder binder, Object[] parameters, CultureInfo culture,
| Boolean v
| erifyAccess)
| at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
| BindingFlags invoke
| Attr, Binder binder, Object[] parameters, CultureInfo culture)
| at SBInvoke.test()
| at SBInvoke.Main(String[] args)
|
|
| Now for the one that works...
|
| D:\development> csc /unsafe sbinvoke.cs /r:sb.dll
| Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
| for Microsoft (R) .NET Framework version 1.1.4322
| Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
|
|
| D:\development>sbinvoke
| ILREF invoke of GetMemory()
|
| abcdefghijklmnopqrstuvwxyz
|
| --file: SBInvoke.cs
| using System;
| using System.Runtime.InteropServices;
| using System.Reflection;
|
| public class SBInvoke
| {
| public unsafe static void test()
| {
| SByte *memory = null;
| #if DYNAMIC
| Console.WriteLine("DYNAMIC invoke of GetMemory()");
|
| Assembly assembly = Assembly.LoadFrom("sb.dll");
| Type type = assembly.GetType("SB");
|
| /* find GetMemory() method */
| MethodInfo method2invoke = null;
| foreach (MethodInfo method in type.GetMethods())
| {
| if (method.Name.CompareTo("GetMemory") == 0)
| method2invoke = method;
| }
|
| object[] parms = { (IntPtr)memory };
|
| int size = (int)method2invoke.Invoke(method2invoke,parms);
|
| byte *countPtr = (byte*)(IntPtr)parms[0];
| #else
| Console.WriteLine("ILREF invoke of GetMemory()");
|
| int size = SB.GetMemory(ref memory);
| byte *countPtr = (byte*)memory;
| #endif
|
| Console.WriteLine();
|
| for(int c=0; c<size; c++)
| {
| Console.Write((char)*countPtr);
| countPtr++;
| }
|
| Console.WriteLine();
| }
|
| public static int Main(string[] args)
| {
| test();
| return 0;
| }
| }
|
| --file: sb.cs
| using System.Runtime.InteropServices;
| using System;
|
| public class SB
| {
| public unsafe static int GetMemory(
| #if DOES_AN_ATTRIBUTE_OR_TWO_HELP
| [MarshalAs(UnmanagedType.LPArray)]
| #endif
| ref SByte *ptr)
| {
| ptr = (SByte*)Marshal.AllocHGlobal(26);
|
| byte *initPtr = (byte*)ptr;
| for(int c=0; c<26; c++)
| *initPtr++=(byte)('a'+(byte)c);
|
| return 26;
| }
| }
|
|
|
|
 
J

Jeffrey Tan[MSFT]

You are welcome.
I am glad I can help you.

Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

--------------------
| Date: Mon, 04 Aug 2003 12:24:36 +0100
| From: Stephen Gennard
<[email protected]>
| User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5b)
Gecko/20030723 Thunderbird/0.1
| X-Accept-Language: en-us, en
| MIME-Version: 1.0
| Subject: Re: Dynamic Invokes and Marshaling a "ref SByte*"
| References: <[email protected]>
<[email protected]>
| In-Reply-To: <[email protected]>
| Content-Type: text/plain; charset=windows-1252; format=flowed
| Content-Transfer-Encoding: 8bit
| Message-ID: <u0SK#[email protected]>
| Newsgroups: microsoft.public.dotnet.languages.csharp
| NNTP-Posting-Host: pix087.mfltd.co.uk 193.129.81.87
| Lines: 1
| Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGP12.phx.gbl
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.languages.csharp:173957
| X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
|
| Thanks that works a treat.
|
| Jeffrey Tan[MSFT] wrote:
|
| > Hi Stephen,
| >
| > I believe the problem lies in here:
| > The GetMemory() function in your dll must be pass the SByte* parameter.
| > This can be done in normal invoke by:
| > int size = SB.GetMemory(ref memory);
| >
| > But in dynamic invoke, the parameter must be passed through Objects
array
| > which can not
| > contain pointer. You convert SByte * to IntPtr and pass it to
GetMemory().
| > IntPtr dose not
| > match SByte parameter, so “Object type cannot be converted to target
type”
| > exception arose.
| >
| > My suggestion is changing the parameter type that must be passed to
| > GetMemory to IntPtr and convert it to
| > SByte* in GetMemory(). Then all will be ok.
| >
| > My source code is listed below:
| >
| > sbinvoke.cs
| >
| > #define DYNAMIC
| > using System;
| > using System.Runtime.InteropServices;
| > using System.Reflection;
| >
| > public class SBInvoke
| > {
| > public unsafe static void test()
| > {
| > try
| > {
| > SByte *p=null;
| > IntPtr memory=new IntPtr (p);
| > #if DYNAMIC
| > Console.WriteLine("DYNAMIC invoke of GetMemory()");
| >
| > Assembly assembly = Assembly.LoadFrom("sb.dll");
| > Type type = assembly.GetType("SB");
| >
| > /* find GetMemory() method */
| > MethodInfo method2invoke = null;
| > foreach (MethodInfo method in type.GetMethods())
| > {
| > if (method.Name.CompareTo("GetMemory") == 0)
| > method2invoke = method;
| > }
| >
| > object[] parms =new object [1];
| > parms[0]=memory;
| >
| > int size = (int)method2invoke.Invoke(method2invoke,parms);
| >
| > byte *countPtr = (byte*)(IntPtr)parms[0];
| > #else
| > Console.WriteLine("ILREF invoke of GetMemory()");
| >
| > int size = SB.GetMemory(ref memory);
| > byte *countPtr = (byte*)memory;
| > #endif
| >
| >
| > Console.WriteLine();
| >
| > for(int c=0; c<size; c++)
| > {
| > Console.Write((char)*countPtr);
| > countPtr++;
| > }
| >
| > Console.WriteLine();
| > }
| > catch(Exception e)
| > {
| > Console.WriteLine("Exception:"+e.Message);
| > }
| > Console.Read ();
| > }
| >
| > public static int Main(string[] args)
| > {
| > test();
| > return 0;
| > }
| > }
| >
| > sb.cs
| >
| > using System.Runtime.InteropServices;
| > using System;
| >
| > public class SB
| > {
| > public unsafe static int GetMemory(
| > #if DOES_AN_ATTRIBUTE_OR_TWO_HELP
| > [MarshalAs(UnmanagedType.LPArray)]
| > #endif
| > ref IntPtr m)
| > {
| > SByte *ptr=(SByte *)m;
| > ptr = (SByte*)Marshal.AllocHGlobal(26);
| > m=(IntPtr)ptr;
| >
| > byte *initPtr = (byte*)ptr;
| > for(int c=0; c<26; c++)
| > *initPtr++=(byte)('a'+(byte)c);
| >
| > return 26;
| > }
| > }
| >
| > This code worked well on my machine.
| > Hope this helps.
| >
| >
| > Jeffrey Tan
| > Microsoft Online Partner Support
| > Get Secure! - www.microsoft.com/security
| > This posting is provided "as is" with no warranties and confers no
rights.
| >
| > --------------------
| > | Message-ID: <[email protected]>
| > | Date: Fri, 01 Aug 2003 11:36:28 +0100
| > | From: Stephen Gennard <[email protected]>
| > | User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.5b)
| > Gecko/20030723 Thunderbird/0.1
| > | X-Accept-Language: en-us, en
| > | MIME-Version: 1.0
| > | Subject: Dynamic Invokes and Marshaling a "ref SByte*"
| > | Content-Type: multipart/mixed;
| > | boundary="------------090005080707020102090809"
| > | Newsgroups: microsoft.public.dotnet.languages.csharp
| > | NNTP-Posting-Host: pix094.mfltd.co.uk 193.129.81.94
| > | Lines: 1
| > | Path: cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!tk2msftngp13.phx.gbl
| > | Xref: cpmsftngxa06.phx.gbl
microsoft.public.dotnet.languages.csharp:173504
| > | X-Tomcat-NG: microsoft.public.dotnet.languages.csharp
| > |
| > | Hello,
| > |
| > | I having a problem dynamically invoking a static method that takes a
| > | reference to a SByte*. If I do it directly it works just fine.
| > |
| > | Anyone any ideas why?
| > |
| > | I have include a example below...
| > |
| > | --
| > | Stephen Gennard
| > | email: (e-mail address removed)
| > |
| > | D:\development>csc /unsafe /target:library /out:sb.dll sb.cs
| > |
| > | Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
| > | for Microsoft (R) .NET Framework version 1.1.4322
| > | Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
| > |
| > |
| > | D:\development\netx45\ilrts\Tests>csc /unsafe /define:DYNAMIC
sbinvoke.cs
| > | Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
| > | for Microsoft (R) .NET Framework version 1.1.4322
| > | Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
| > |
| > |
| > | D:\development>sbinvoke
| > | DYNAMIC invoke of GetMemory()
| > |
| > | Unhandled Exception: System.ArgumentException: Object type cannot be
| > | converted t
| > | o target type.
| > | at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj,
| > | BindingFlag
| > | s invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture,
| > | Boolean i
| > | sBinderDefault, Assembly caller, Boolean verifyAccess)
| > | at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj,
| > | BindingFlag
| > | s invokeAttr, Binder binder, Object[] parameters, CultureInfo
culture,
| > | Boolean v
| > | erifyAccess)
| > | at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,
| > | BindingFlags invoke
| > | Attr, Binder binder, Object[] parameters, CultureInfo culture)
| > | at SBInvoke.test()
| > | at SBInvoke.Main(String[] args)
| > |
| > |
| > | Now for the one that works...
| > |
| > | D:\development> csc /unsafe sbinvoke.cs /r:sb.dll
| > | Microsoft (R) Visual C# .NET Compiler version 7.10.3052.4
| > | for Microsoft (R) .NET Framework version 1.1.4322
| > | Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.
| > |
| > |
| > | D:\development>sbinvoke
| > | ILREF invoke of GetMemory()
| > |
| > | abcdefghijklmnopqrstuvwxyz
| > |
| > | --file: SBInvoke.cs
| > | using System;
| > | using System.Runtime.InteropServices;
| > | using System.Reflection;
| > |
| > | public class SBInvoke
| > | {
| > | public unsafe static void test()
| > | {
| > | SByte *memory = null;
| > | #if DYNAMIC
| > | Console.WriteLine("DYNAMIC invoke of GetMemory()");
| > |
| > | Assembly assembly = Assembly.LoadFrom("sb.dll");
| > | Type type = assembly.GetType("SB");
| > |
| > | /* find GetMemory() method */
| > | MethodInfo method2invoke = null;
| > | foreach (MethodInfo method in type.GetMethods())
| > | {
| > | if (method.Name.CompareTo("GetMemory") == 0)
| > | method2invoke = method;
| > | }
| > |
| > | object[] parms = { (IntPtr)memory };
| > |
| > | int size = (int)method2invoke.Invoke(method2invoke,parms);
| > |
| > | byte *countPtr = (byte*)(IntPtr)parms[0];
| > | #else
| > | Console.WriteLine("ILREF invoke of GetMemory()");
| > |
| > | int size = SB.GetMemory(ref memory);
| > | byte *countPtr = (byte*)memory;
| > | #endif
| > |
| > | Console.WriteLine();
| > |
| > | for(int c=0; c<size; c++)
| > | {
| > | Console.Write((char)*countPtr);
| > | countPtr++;
| > | }
| > |
| > | Console.WriteLine();
| > | }
| > |
| > | public static int Main(string[] args)
| > | {
| > | test();
| > | return 0;
| > | }
| > | }
| > |
| > | --file: sb.cs
| > | using System.Runtime.InteropServices;
| > | using System;
| > |
| > | public class SB
| > | {
| > | public unsafe static int GetMemory(
| > | #if DOES_AN_ATTRIBUTE_OR_TWO_HELP
| > | [MarshalAs(UnmanagedType.LPArray)]
| > | #endif
| > | ref SByte *ptr)
| > | {
| > | ptr = (SByte*)Marshal.AllocHGlobal(26);
| > |
| > | byte *initPtr = (byte*)ptr;
| > | for(int c=0; c<26; c++)
| > | *initPtr++=(byte)('a'+(byte)c);
| > |
| > | return 26;
| > | }
| > | }
| > |
| > |
| > |
| > |
| >
|
|
 

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