Reputation: 222
I am writing a Visual Studio add in and need to marshall a managed CodeElements object to it's unmananged form. I just need the pointer in memory, as I can cast it and treat it like a CodeElement on the unmanaged side.
[DllImport("CodeMethodsToString.dll")]
private static extern BSTR* CodeMethodsToString(void* functionObject);
public static void CodeMethodsToXML(XmlElement parent, CodeElements elements)
{
//Call CodeMethodsToString: how do I marshall CodeElements to an IntPtr?
//set XmlElement in here
}
I know how to deal with the XML, and I have a working version of this in C#. I created the unmanaged DLL because calling all of the various member variables at the lowest level of recursion was killing the speed of the program. I simply need to know how to use System.Runtime.Interop.Marshal to convert the CodeElements object to a pointer to the COM object in memory.
Thanks.
Upvotes: 1
Views: 3281
Reputation: 11
You can optionally check out the example at the end of the article: GCHandle MSDN
Upvotes: 1
Reputation: 28701
Looks like Jonathan was close. This is how I'd do it:
[DllImport("CodeMethodsToString.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string CodeMethodsToString(IntPtr functionObject);
public static void CodeMethodsToXML(XmlElement parent, CodeElements elements)
{
GCHandle pin;
try
{
pin = GcHandle.Alloc(elements, GCHandleType.Pinned);
string methods = CodeMethodsToString(pin.AddrOfPinnedObject());
}
finally
{
pin.Free();
}
}
Upvotes: 3
Reputation: 7285
As soon as you see a star or ampersand you should start by converting it to ref (safe version of a pointer). I have had reference types magically start working when I used the ref keyword in the past (which is highly contradictory - but I think it's one of those interop things):
[DllImport("example.dll")]
private static extern void DoStuff(ref CodeElements codeElements);
You could also try:
[DllImport("example.dll")]
private static extern void DoStuff([In, Out] ref CodeElements codeElements);
Or one of the permutations of those attributes.
One thing you might want to try is to use the MFC (I think, been a long time since C++) to make the COM library. Don't use a native call, export the thing as a type library and add it as a reference in Visual Studio (yes, it's that easy). Thus you will land up with something like:
myCoolClass.DoStuff(codeElements);
You might also want to pin it (if you need to pin it the error will be intermittent). I can't remember if the RCW will do that for you (I am almost certain it will), so here is the code to do it:
GCHandle handle = new GCHandle();
try
{
handle = GCHandle.Alloc(fooz, GCHandleType.Pinned);
// Use fooz.
}
finally
{
if (handle.IsAllocated)
handle.Free();
}
Upvotes: 1
Reputation: 217313
Is CodeElements
a ComVisible
interface and has a GuidAttribute
?
Then C# will do the marshalling of COM objects for you, and you can simply use CodeElements
as argument type:
[DllImport("example.dll")]
private static extern void DoStuff(CodeElements codeElements);
Upvotes: 1