Using callback from Marshal::GetFunctionPointerForDelegate changes managed array argument - c#

Here is my unmanaged code:
delegate void MyDelegate(array<int>^% arguments);
typedef void (__stdcall *MyCallback)(array<int>^% arguments);
void Test(MyDelegate^ delegate)
{
MyCallback myCallback = static_cast<MyCallback>(Marshal::GetFunctionPointerForDelegate(delegate).ToPointer());
array<int>^ foo = gcnew array<int>(5);
foo[0] = 1;
foo[1] = 2;
foo[2] = 3;
foo[3] = 4;
foo[4] = 5;
myCallback(foo);
}
result:
The delegate is called, but array.Length of the argument in delegate is one instead of five. The first element in the array is correct. After the callback foo.Length() is also one! Can anyone tell me why??
More infomation:
I am using C++/CLI to wrap a C++ library so that it can be accessed by C#. The C++ library uses member function pointers (FastDelegate) to achieve a type of unmanaged "delegate". I need to provide one of these "FastDelegate" member function pointers that eventually calls a c# delegate. To achieve this it seems I need to do one of the following:
Store a delegate reference in an unmanaged (non ref) class.
Get the address of a managed class to pass to an unmanaged class. (So that I can use a member function pointer to it.)
Something else?
Any ideas?

Related

c# / c++ member function pointers

Is it possible to store member functions in C++ the way delegates are used in C#?
How do Delegates accomplish the object-instance, memberFuncPtr pairs and calls without knowing anything about the instance class?
(note: this questions arose while I was trying to understand events/delegates in publisher/subscriber code design)
I read that:
C++ requires knowledge of a class type such as ClassType::*FuncPtr
C# delegates allow someDelegate += classInstance.memberFunc
There is type called std::function,but if you are using older version of C++ (older than C++11) you will need to use raw function pointers.Check function pointers in C,they are the same for C++.
Not getting exactly what you are asking.
But you can store member functions in form of function pointers in c++.
void yourFunc(int x);
int main()
{
void (*funcPtr)(int)=&yourFunc;
(*funcPtr)(10);
}
Or
A normal function with an int parameter
// and void return type
void fun(int a)
{
printf("Value of a is %d\n", a);
}
int main()
{
// fun_ptr is a pointer to function fun()
void (*fun_ptr)(int) = &fun;
/* The above line is equivalent of following two
void (*fun_ptr)(int);
fun_ptr = &fun;
*/
// Invoking fun() using fun_ptr
(*fun_ptr)(10);
return 0;
}

How to pass this pointer as context parameter for callback in c#

In C++ it's common to pass the 'this' pointer to a callback registration method so that the callback will receive this pointer back. I have a 3rd party library that i am trying to interop with from C# that uses this pattern.
Ex.
typedef HRESULT (WINAPI PFNCALLBACK*)(CALLBACKDATA *data, void *context);
HRESULT SetCallback (PFNCALLBACK *callback, void *context);
I've defined a delegate for the callback function:
public delegate int Callback(IntPtr context, CallbackData sample);
and call the SetCallback function
void SetupCallback()
{
// My stab at passing the this pointer as context for the callback
IntPtr pThis = GCHandle.ToIntPtr(GCHandle.Alloc(this));
hr = obj.SetCallback(OnCallback, pThis);
}
public static int OnCallback(CallbackData data, IntPtr context)
{
// HOW do I reconstitute the This pointer from the context parameter
}
My question is how do I pass a C# 'this' pointer to the SetCallback method and reconstitute it in the callback function?
Ugh, you are asking for an interop nightmare, especially since you are dealing with a "black box" third party DLL.
Having said that, theoretically this should be possible by utilizing the
UnmanagedFunctionPointer attribute.
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate int Callback(IntPtr context, CallbackData sample);
Then store off your delegate
static Callback _someCallBack = null;
_someCallBack += new Callback(OnCallback);
Finally pass in the delegate when calling the C code
IntPtr pThis = GCHandle.ToIntPtr(GCHandle.Alloc(this));
hr = obj.SetCallback(_someCallBack, pThis);
I also don't think you even really need to mess with the this pointer, unless you really need it in the callback honestly I would try passing in null. It's not safe in .Net land to marshall and marshall references back and re-use it.

C# ref is it like a pointer in C/C++ or a reference in C++?

I'm working with the ref and don't understand clearly "Is it like a pointer as in C/C++ or it's like a reference in C++?"
Why did I ask such a weak question as you thought for a moment?
Because, when I'm reading C#/.NET books, msdn or talking to C# developers I'm becoming confused by the following reasons:
C# developers suggest NOT to use ref in the arguments of a function, e.g. ...(ref Type someObject) doesn't smell good for them and they suggest ...(Type someObject), I really don't understand clearly this suggestion. The reasons I heard: better to work with the copy of object, then use it as a return value, not to corrupt memory by a reference etc... Often I hear such explanation about DB connection objects. As on my plain C/C++ experience, I really don't understand why to use a reference is a bad stuff in C#? I control the life of object and its memory allocations/re-allocations etc... I read in books and forums only advises it's bad, because you can corrupt your connection and cause a memory leak by a reference lose, so I control the life of object, I may control manually what I really want, so why is it bad?
Nowadays reading different books and talk to different people, I don't clearly understand is ref a pointer (*) or a reference like in C++ by & ? As I remember pointers in C/C++ always do allocate a space with a size of void* type - 4 bytes (the valid size depends on architecture), where hosts an address to a structure or variable. In C++ by passing a reference & there is no new allocations from the heap/stack and you work with already defined objects in memory space and there is no sub-allocating memory for a pointer externally like in plain C. So what's the ref in C#? Does .NET VM handle it like a pointer in plain C/C++ and its GC allocates temporary space for a pointer or it does a work like reference in C++? Does ref work only with a managed types correctly or for value types like bool, int it's better to switch an unsafe code and pass through a pointer in unmanaged style?
In C#, when you see something referring to a reference type (that is, a type declared with class instead of struct), then you're essentially always dealing with the object through a pointer. In C++, everything is a value type by default, whereas in C# everything is a reference type by default.
When you say "ref" in the C# parameter list, what you're really saying is more like a "pointer to a pointer." You're saying that, in the method, that you want to replace not the contents of the object, but the reference to the object itself, in the code calling your method.
Unless that is your intent, then you should just pass the reference type directly; in C#, passing reference types around is cheap (akin to passing a reference in C++).
Learn/understand the difference between value types and reference types in C#. They're a major concept in that language and things are going to be really confusing if you try to think using the C++ object model in C# land.
The following are essentially semantically equivalent programs:
#include <iostream>
class AClass
{
int anInteger;
public:
AClass(int integer)
: anInteger(integer)
{ }
int GetInteger() const
{
return anInteger;
}
void SetInteger(int toSet)
{
anInteger = toSet;
}
};
struct StaticFunctions
{
// C# doesn't have free functions, so I'll do similar in C++
// Note that in real code you'd use a free function for this.
static void FunctionTakingAReference(AClass *item)
{
item->SetInteger(4);
}
static void FunctionTakingAReferenceToAReference(AClass **item)
{
*item = new AClass(1729);
}
};
int main()
{
AClass* instanceOne = new AClass(6);
StaticFunctions::FunctionTakingAReference(instanceOne);
std::cout << instanceOne->GetInteger() << "\n";
AClass* instanceTwo;
StaticFunctions::FunctionTakingAReferenceToAReference(&instanceTwo);
// Note that operator& behaves similar to the C# keyword "ref" at the call site.
std::cout << instanceTwo->GetInteger() << "\n";
// (Of course in real C++ you're using std::shared_ptr and std::unique_ptr instead,
// right? :) )
delete instanceOne;
delete instanceTwo;
}
And for C#:
using System;
internal class AClass
{
public AClass(int integer)
: Integer(integer)
{ }
int Integer { get; set; }
}
internal static class StaticFunctions
{
public static void FunctionTakingAReference(AClass item)
{
item.Integer = 4;
}
public static void FunctionTakingAReferenceToAReference(ref AClass item)
{
item = new AClass(1729);
}
}
public static class Program
{
public static void main()
{
AClass instanceOne = new AClass(6);
StaticFunctions.FunctionTakingAReference(instanceOne);
Console.WriteLine(instanceOne.Integer);
AClass instanceTwo = new AClass(1234); // C# forces me to assign this before
// it can be passed. Use "out" instead of
// "ref" and that requirement goes away.
StaticFunctions.FunctionTakingAReferenceToAReference(ref instanceTwo);
Console.WriteLine(instanceTwo.Integer);
}
}
A ref in C# is equivalent to a C++ reference:
Their intent is pass-by-reference
There are no null references
There are no uninitialized references
You cannot rebind references
When you spell the reference, you are actually denoting the referred variable
Some C++ code:
void foo(int& x)
{
x = 42;
}
// ...
int answer = 0;
foo(answer);
Equivalent C# code:
void foo(ref int x)
{
x = 42;
}
// ...
int answer = 0;
foo(ref answer);
Every reference in C# is pointer to objects on heap as pointer in C++ and ref of C# is same as & in C++
The reason ref should be avoided is, C# works on fundamental that method should not change the object passed in parameter, because for someone who does not have source of method may not know if it will result in loss of data or not.
String a = " A ";
String b = a.Trim();
In this case I am confident that a remains intact. In mathematics change should be seen as an assignment that visually tells is that b is changed here by programmer's consent.
a = a.Trim();
This code will modify a itself and the coder is aware of it.
To preserve this method of change by assignment ref should be avoided unless it is exceptional case.
C# has no equvalent of C++ pointers and works on references. ref adds a level of indirection. It makes value type argument a reference and when used with reference type it makes it a reference to a reference.
In short it allows to carry any changes to a value type outside a method call. For reference type it allows to replace the original reference to a totally different object (and not just change object content). It can be used if you want to re-initialize an object inside a method and the only way to do it is to recreate it. Although I would try avoid such an approach.
So to answer your question ref would be like C++ reference to a reference.
EDIT
The above is true for safe code. Pointers do exist in unsafe C# and are used in some very specific cases.
This seems like a disposing/eventing nightmare. If I have an object who's events are registered for and pass it into a function by reference and that reference is then reallocated, the dispose should be called or the memory will be allocated until the program is closed. If the dispose is called everything registered to the objects events will no longer be registered for and everything it is registered for will no longer be registered for. How would someone keep this straight? I guess you could compare memory addresses and try to bring things back to sanity if you don't go insane.
in c# you can check run unsafe in your project properties
and then you can run this code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Exercise_01
{
public struct Coords
{
public int X;
public int Y;
public override string ToString() => $"({X}, {Y})";
}
class Program
{
static unsafe void Main(string[] args)
{
int n = 0;
SumCallByRefPointer(1, 2, &n);
Console.Clear();
Console.WriteLine("call by refrence {0}",n);
n = 0;
SumCallByValue(3, 4, n);
Console.WriteLine("call by Value {0}", n);
n = 0;
SumCallByRef(5, 6, ref n);
Console.WriteLine("call by refrence {0}", n);
Pointer();
Console.ReadLine();
}
private static unsafe void SumCallByRefPointer(int a, int b, int* c)
{
*c = a + b;
}
private static unsafe void SumCallByValue(int a, int b, int c)
{
c = a + b;
}
private static unsafe void SumCallByRef(int a, int b, ref int c)
{
c = a + b;
}
public static void Pointer()
{
unsafe
{
Coords coords;
Coords* p = &coords;
p->X = 3;
p->Y = 4;
Console.WriteLine(p->ToString()); // output: (3, 4)
}
}
}
}

Marshalling an array of strings from managed to native code

I have a managed function with the following declaration (both interface and implementation):
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
String[] ManagedFunction()
{
String[] foo = new String[1];
foo[0] = "bar";
return foo;
}
There is also a native C++ interface with the same methods as the managed interface, inside of that interface, this method has the following declaration:
void ManagedFunction(SAFEARRAY* foo);
This function is called by native code in the following way:
void NativeFunction(ManagedBinding binding)
{
CComSafeArray<BSTR> cComSafeArray;
cComSafeArray.Create();
LPSAFEARRAY safeArray = cComSafeArray.Detach();
binding.comObject->ManagedFunction(safeArray);
}
I'm not sure what I'm doing wrong but after my managed function has been called, safeArray appears to have garbage values, somethings going wrong while marshalling the return value back to native code. Could someone with more experience than me with .Net interop please shed some light on this? Also, It might be relevant to mention that I haven't had problems with returning ValueTypes from my managed function (boolean if you're curious), something about returning a String array is messing things up. Thanks!
1) Your function return a SAFEARRAY, so why you allocate it before calling function?
2) ManagedFunction supposed to return a SAFEARRAY, so it should get a SAFEARRAY* to be able to return it! so you should say:
LPSAFEARRAY lpsa;
binding.comObject->ManagedFunction(&lpsa);
CComSafeArray<BSTR> cComSafeArray;
cComSafeArray.Attach(lpsa);
Well I finally got it to work. I created a managed representation of SAFEARRAY called ManagedSafeArray (stolen from here : http://social.msdn.microsoft.com/Forums/en-US/clr/thread/6641abfc-3a9c-4976-a523-43890b2b79a2/):
[StructLayout(LayoutKind.Sequential)]
struct ManagedSafeArray
{
public ushort dimensions; // Count of dimensions in the SAFEARRAY
public ushort features; // Flags to describe SAFEARRAY usage
public uint elementSize; // Size of an array element
public uint locks; // Number of times locked without unlocking
public IntPtr dataPtr; // Pointer to the array data
public uint elementCount; // Element count for first (only) dimension
public int lowerBound; // Lower bound for first (only) dimension
}
I changed the signature of my method to:
void ManagedMethod(ref ManagedSafeArray foo);
Inside my method, I manually updated the dataPtr field by calling Marshal.AllocCoTaskMem(...) and then copied over the strings I wanted the SAFEARRAY to contain.
I have no idea as to why the CLR wasn't able to automatically marshal the parameters to and from native code and I'd still appreciate it if someone could try to explain that.

Invalid Variant crash

I have a situation where I've wrapped a Native C++ DLL with C++/CLI for eventual use in C#.
There are a few callback functions that are causing some issues at run time. Particularly, I get the following exception:
An unhandled exception of type
'System.Runtime.InteropServices.InvalidOleVariantTypeException'
occurred in ToadWrapTest.dll
Additional information: Specified OLE
variant is invalid.
On this line of code (C++/CLI):
public delegate int ManagedCallbackFunction (Object^ inst, const Object^ data);
public delegate int UnManagedCallbackFunction (void* inst, const void* data);
ManagedCallbackFunction^ m_callbackFn;
int intermidiaryCallback(void * pInstance, const void * pData)
{
void* temp = (void*)pData;
System::IntPtr ip1 = IntPtr(pInstance);
System::IntPtr ip2 = IntPtr(temp);
Object^ oInst = Marshal::GetObjectForNativeVariant(ip1);
Object^ oData = Marshal::GetObjectForNativeVariant(ip2);
//invoke the callback to c#
//return m_callbackFn::Invoke(oInst, oData);
return 0;
};
The reason I've made this "intermediary callback" was an attempt to circumvent the Invalid variant exception being thrown when I tried to directly map the delegate from C# to the native C++ code. As an attempted work-around, I declare a delegate on the C# side and pass that funcptr to the C++/CLI wrapper. I then pass the intermediary funcptr to the native C++ and just daisy chain the calls together.
What I know is that it all works in native C++ world. The problem is mapping the void* to the managed world. The following code shows the native C++ version of the callback:
int (*CallbackFunction) (void *inst, const void *data);
If anyone can help here, I'd really appreciate it.
Are pInstance and pData really VARIANT? If they are, I would expect your callback function to be more strongly typed:
int (*CallbackFunction)(VARIANT *inst, VARIANT *data);
If that's the case, in your code you should be able to look at the actual VARIANT to hand check it. If you are not really getting VARIANTs (ie, you are really just getting void * pointers), you shouldn't try to turn them into C# objects since there is no inherent meaning to them. They should get passed through as IntPtr. If you know that they should have some other type of inherent meaning, you need to marshal them as appropriate types.
Big Thanks to plinth on this one! I am posting the final solution below to anyone else who has to deal with 3rd party fun like this one! Please feel free to critique, as I am not done optimizing the code. This may still be to roundabout a solution.
First, the callback functions became:
public delegate int ManagedCallbackFunction (IntPtr oInst, IntPtr oData);
public delegate int UnManagedCallbackFunction (void* inst, const void* data);
ManagedCallbackFunction^ m_callbackFn;
Big props on this one. It just plain won't work if you try to cast from void* directly to Object^. Using the IntPtr and my intermediary callback:
int intermidiaryCallback(void * pInstance, const void * pData)
{
void* temp = (void*)pData;
return m_callbackFn->Invoke(IntPtr(pInstance), IntPtr(temp));
};
We finally get a working model on the C# side with some massaging of the objects:
public static int hReceiveTestMessage(IntPtr pInstance, IntPtr pData)
{
// provide object context for static member function
helloworld2 hw = (helloworld2)GCHandle.FromIntPtr(pInstance).Target;
if (hw == null || pData == null)
{
Console.WriteLine("hReceiveTestMessage received NULL data or instance pointer\n");
return 0;
}
// populate message with received data
IntPtr ip2 = GCHandle.ToIntPtr(GCHandle.Alloc(new DataPacketWrap(pData)));
DataPacketWrap dpw = (DataPacketWrap)GCHandle.FromIntPtr(ip2).Target;
uint retval = hw.m_testData.load_dataSets(ref dpw);
// display message contents
hw.displayTestData();
return 1;
}
I mention "massaging" the objects because the delegate is not specific to this callback function and I don't know what object pData will be until run time(from the delegates POV). Because of this issue, I have to do some extra work with the pData object. I basically had to overload the constructor in my wrapper to accept an IntPtr. Code is provided for full "clarity":
DataPacketWrap (IntPtr dp)
{
DataPacket* pdp = (DataPacket*)(dp.ToPointer());
m_NativeDataPacket = pdp;
};

Categories

Resources