Call function from pointer
-
Hi, I've searched everywhere! Does anyone here know how to call a function from C# from an IntPtr? I know how to obtain the function pointer: IntPtr ptr = (typeof(SOMECLASS).GetMethod("SomeMethodName").MethodHandle.GetFunctionPointer()) Now I just need a way to call it .. The reason I need this is because in MSHTML, there is an interface called IHTMLElementRender, and the function 'DrawToDC' (useful for capturing HTML documents as an image) takes the argument HDC, but is implemented to take a reference variable of an unrelated structure. Therefore I need to call the function by the pointer, as in C++. Thanks! - Joe Esposito
-
Hi, I've searched everywhere! Does anyone here know how to call a function from C# from an IntPtr? I know how to obtain the function pointer: IntPtr ptr = (typeof(SOMECLASS).GetMethod("SomeMethodName").MethodHandle.GetFunctionPointer()) Now I just need a way to call it .. The reason I need this is because in MSHTML, there is an interface called IHTMLElementRender, and the function 'DrawToDC' (useful for capturing HTML documents as an image) takes the argument HDC, but is implemented to take a reference variable of an unrelated structure. Therefore I need to call the function by the pointer, as in C++. Thanks! - Joe Esposito
You've run into one of the limitations of IDL: it was originally for describing structures to be marshalled across processes, but some things we'd like to describe in IDL - handles to GDI and USER objects - are process-relative and have no meaning in another process. So the IDL contains a fake definition. I've browsed Google Groups for
_RemotableHandle
. The recommended answer is apparently to use ILDASM to generate IL code for the interface, change the declaration to take anIntPtr
, then recompile it. Not nice. I'd actually recommend using Managed C++ to wrap the interface as declared in mshtml.h. Stability. What an interesting concept. -- Chris Maunder -
Hi, I've searched everywhere! Does anyone here know how to call a function from C# from an IntPtr? I know how to obtain the function pointer: IntPtr ptr = (typeof(SOMECLASS).GetMethod("SomeMethodName").MethodHandle.GetFunctionPointer()) Now I just need a way to call it .. The reason I need this is because in MSHTML, there is an interface called IHTMLElementRender, and the function 'DrawToDC' (useful for capturing HTML documents as an image) takes the argument HDC, but is implemented to take a reference variable of an unrelated structure. Therefore I need to call the function by the pointer, as in C++. Thanks! - Joe Esposito
Instead of wrapping this with an MC++ assembly as the first reply states, just interop the interface yourself. Such it's such a simple interface, it won't be hard:
[ComImport, Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IHTMLElementRender
{
void DrawToDc(IntPtr hdc);
void SetDocumentPrinter(
[MarshalAs(UnmanagedType.BStr)] string printerName, IntPtr hdc);
}You could then use
Marshal.GetComInterfaceForObject
to get a pointer to this interface. You then callMarshal.GetObjectForIUnknown
and cast to the interface like so:IntPtr ptr = Marshal.GetComInterfaceForObject(element,
typeof(IHTMLElementRender)); // Interface type from above
IHTMLElementRender render = (IHTMLElementRender)Marshal.GetObjectForIUnknown(
ptr);
render.DrawToDc(hdc);
// IUknown::Release will be called when 'render' is GC'd, but you must
// release the IntPtr from GetComInterfaceForObject.
Marshal.Release(ptr);Please note that this is untested but I've used similar code with different interfaces before with success. I hope this helps.
Microsoft MVP, Visual C# My Articles
-
Instead of wrapping this with an MC++ assembly as the first reply states, just interop the interface yourself. Such it's such a simple interface, it won't be hard:
[ComImport, Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IHTMLElementRender
{
void DrawToDc(IntPtr hdc);
void SetDocumentPrinter(
[MarshalAs(UnmanagedType.BStr)] string printerName, IntPtr hdc);
}You could then use
Marshal.GetComInterfaceForObject
to get a pointer to this interface. You then callMarshal.GetObjectForIUnknown
and cast to the interface like so:IntPtr ptr = Marshal.GetComInterfaceForObject(element,
typeof(IHTMLElementRender)); // Interface type from above
IHTMLElementRender render = (IHTMLElementRender)Marshal.GetObjectForIUnknown(
ptr);
render.DrawToDc(hdc);
// IUknown::Release will be called when 'render' is GC'd, but you must
// release the IntPtr from GetComInterfaceForObject.
Marshal.Release(ptr);Please note that this is untested but I've used similar code with different interfaces before with success. I hope this helps.
Microsoft MVP, Visual C# My Articles
Thanks! That did exactly what I needed it to! I did consider using this method, however all of my attempts failed and left me clueless. It seems that this attribute really makes the difference: InterfaceType(ComInterfaceType.InterfaceIsIUnknown) Without it, the program simply crashes when you try to use it. Also, I have been using type-casts where QueryInterface would be required. It also worked in this case: IHTMLElementRender render = (IHTMLElementRender)element; render.DrawToDc(hdc); Thanks again for your reply :) - Joe
-
Thanks! That did exactly what I needed it to! I did consider using this method, however all of my attempts failed and left me clueless. It seems that this attribute really makes the difference: InterfaceType(ComInterfaceType.InterfaceIsIUnknown) Without it, the program simply crashes when you try to use it. Also, I have been using type-casts where QueryInterface would be required. It also worked in this case: IHTMLElementRender render = (IHTMLElementRender)element; render.DrawToDc(hdc); Thanks again for your reply :) - Joe
When you perform a type-cast, the CLR performs a QI (
QueryInterface
). In some cases, however, the compiler will complain if the object (if it's type is known) doesn't and never could implement that interface. Glad it works for you.Microsoft MVP, Visual C# My Articles