Discussion:
Marshaling objects as pointer only!
(too old to reply)
Atmapuri
2010-01-30 15:25:13 UTC
Permalink
Hi!

I have an unmanaged function:

void Fun1(void * Delegate1, void * Param);

which I call from managed code via PInvoke.
The managed Delegate1 is then called from unmanaged code
like this:

public static void Delegate1(void * Param)
{
...
}

This all works fine. The problem is that the "Param" I need
to pass to Fun1 is a big and complex managed object. If I don't pass it
to the function, I have to use global variable and the routine
is not thread safe. The Fun1 does not end until all Delegate1 calls
have finished. (blocking call).

The question is therefore:

How can you pass a pointer to a managed object and have that
managed object than available within Delegate1 as the true CLR
object? If I define the type directly, the program simply halts.

Thanks!
Atmapuri
Jeroen Mostert
2010-01-30 21:43:21 UTC
Permalink
Post by Atmapuri
How can you pass a pointer to a managed object and have that
managed object than available within Delegate1 as the true CLR
object?
Use GCHandle.Alloc(), GCHandle.ToIntPtr(), GCHandle.FromIntPtr() and last
but certainly not least GCHandle.Free(). This is assuming the unmanaged code
does not need to access the managed object at all but just needs to pass an
opaque pointer.
--
J.
Atmapuri
2010-01-31 08:44:49 UTC
Permalink
Hi!

GCHandle.Alloc called with "pinned" parameter gives an error message:

"Object contains non-primitive or non-blittable data."

That is not a problem though for what I would like to do. I know that data
is not blittable. However, If the object is not pinned, then the unmanaged
code can
make copies of the pointer and pass references with the wrong address.

The GC can do whatever it wants with the contents of the object, but
it may not move it.

Thanks!
Atmapuri
Post by Jeroen Mostert
Post by Atmapuri
How can you pass a pointer to a managed object and have that
managed object than available within Delegate1 as the true CLR
object?
Use GCHandle.Alloc(), GCHandle.ToIntPtr(), GCHandle.FromIntPtr() and last
but certainly not least GCHandle.Free(). This is assuming the unmanaged
code does not need to access the managed object at all but just needs to
pass an opaque pointer.
--
J.
Jeroen Mostert
2010-02-01 22:44:11 UTC
Permalink
Post by Atmapuri
GCHandle.Alloc called with "pinned" parameter gives an error message
Don't pin it, there's no need to (from what I've understood what you're doing).

Pinning is only necessary if the object is accessed at all. If it's not, all
that matters is that the value of the GCHandle remain the same (which it
will). This is unrelated to the location of the managed data in memory. A
GCHandle is, as the name implies, a handle. It's *not* a pointer, it just
converts to one. A pinned GCHandle is special in that it actually converts
to a pointer to the object, but this is not what you usually need.
Post by Atmapuri
That is not a problem though for what I would like to do. I know that data
is not blittable. However, If the object is not pinned, then the
unmanaged code can
make copies of the pointer and pass references with the wrong address.
Is the pointer dereferenced by unmanaged code or not? You never make this
clear. If it's not, then it really doesn't matter *what* you pass to the
unmanaged code, whether it makes copies of that value, etc. All that matters
is that the value can be uniquely translated to an object when you get it
back, and this is exactly what GCHandle arranges.

To give a concrete example, let's say you only ever pass three objects to
unmanaged code. You could simply number these objects 1, 2, 3 and pass these
values to the unmanaged code. As long as the unmanaged code never tries to
dereference these "pointers", it doesn't matter that they're not actual
pointers or whether the managed object is moving in memory. When you get
back the value you'll know which managed object was meant. This (simplified)
is what a non-pinned GCHandle does.
Post by Atmapuri
The GC can do whatever it wants with the contents of the object, but
it may not move it.
Again, it's not clear what you want, but you seem to misunderstand what
GCHandle does in any case.
--
J.
Jeroen Mostert
2010-02-01 23:32:33 UTC
Permalink
A pinned GCHandle is special in that it actually converts to a pointer to the object
This needs clarification: GCHandle.AddrOfPinnedObject() will work for pinned
GCHandles (and pinned handles only). GCHandle.ToIntPtr() will work for all
handles, but will not yield a pointer to the object in any case.
--
J.
Atmapuri
2010-02-25 12:09:41 UTC
Permalink
Hi!

It became clear to me that GCHandle.ToIntPtr()
actually deals with the pointer to the Handle
itself which in turn contains the pointer to the object.

Thanks!
Atmapuri
Post by Jeroen Mostert
A pinned GCHandle is special in that it actually converts to a pointer to the object
This needs clarification: GCHandle.AddrOfPinnedObject() will work for
pinned GCHandles (and pinned handles only). GCHandle.ToIntPtr() will work
for all handles, but will not yield a pointer to the object in any case.
--
J.
Fábio Chicout
2010-02-02 13:19:26 UTC
Permalink
Is it possible to make interop on the inverse way? I mean, a C#.NET Assembly
called by a C++/C executable?
What are the ways we can accomplish this?

Fábio Chicout
Post by Atmapuri
Hi!
void Fun1(void * Delegate1, void * Param);
which I call from managed code via PInvoke.
The managed Delegate1 is then called from unmanaged code
public static void Delegate1(void * Param)
{
...
}
This all works fine. The problem is that the "Param" I need
to pass to Fun1 is a big and complex managed object. If I don't pass it
to the function, I have to use global variable and the routine
is not thread safe. The Fun1 does not end until all Delegate1 calls
have finished. (blocking call).
How can you pass a pointer to a managed object and have that
managed object than available within Delegate1 as the true CLR
object? If I define the type directly, the program simply halts.
Thanks!
Atmapuri
MarkusSchaber
2010-02-03 13:05:36 UTC
Permalink
Hi, Fábio,
Post by Fábio Chicout
Is it possible to make interop on the inverse way? I mean, a C#.NET Assembly
called by a C++/C executable?
What are the ways we can accomplish this?
First, you should start a new thread for a new question.

Second, AFAICS, you have two ways to accomplish this:

- Embedding the CLR explicitly.

- Using COM with registered types.
Loading...