tag:blogger.com,1999:blog-362796945673239800.post913827605849520990..comments2023-02-17T04:48:02.178-05:00Comments on Technical Is As Technical Does - Hugh Ang's Blog: Reverse P/InvokeHugh Anghttp://www.blogger.com/profile/09609747815666754891noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-362796945673239800.post-49192426363812599762016-09-28T15:59:52.622-04:002016-09-28T15:59:52.622-04:00Hello, Hugh,
I created a tool to automate generat...Hello, Hugh,<br /><br />I created a tool to automate generating a native DLL to call .NET assembly from native C++ application without the need to create the mixed mode assembly using C++/CLI. Would yo like to try it and let me know how you feel about it?<br /><br /><a href="http://www.xinterop.com/index.php/xinterop-native-c-to-net-bridge/" rel="nofollow"><b>xInterop Native C++ to .NET Bridge</b></a><br /><br />Disclainer: I am the author.<br /><br />Happy coding.<br /><br />ShawnAnonymoushttps://www.blogger.com/profile/16934444454747657901noreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-10025385373763840952016-09-25T18:45:37.461-04:002016-09-25T18:45:37.461-04:00To the last post:
Yes you can use MSVC 2015 just ...To the last post:<br /><br />Yes you can use MSVC 2015 just fine. The InteropBridge, which defines the fnInteropBridge, is the C++/CLI project and it needs to export the API like so:<br /><br /><br />#define INTEROPBRIDGE_API __declspec(dllexport)<br /><br />INTEROPBRIDGE_API TCHAR* fnInteropBridge(MessageData data)<br />{<br /> ManagedLibrary::UsefulThing^ c = gcnew ManagedLibrary::UsefulThing();<br /> System::IntPtr p = Marshal::GetFunctionPointerForDelegate(c->GetDelegate());<br /><br /> NativeToManaged funcPointer = (NativeToManaged)p.ToPointer();<br /><br /> // invoke the delegate<br /> return funcPointer(data);<br />}<br /><br />Then in your native C++ project, just link to the InteropBridge and yes you will need to declare the struct (perhaps share the same header file between the two projects). <br /><br />I do have a working sample in MSVC 2015. If you want, you can email me at hugh.ang at gmail.com - I can send it to you. <br /><br />Cheers<br />Hugh<br /> Hugh Anghttps://www.blogger.com/profile/09609747815666754891noreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-3899465521965441152016-09-25T18:12:12.968-04:002016-09-25T18:12:12.968-04:00Hi, I can follow most of your example. I have a .N...Hi, I can follow most of your example. I have a .NET 3.5 C# dll that was compiled with MSVC 2015 just fine and works for other purposes before I tried to use it with reverse p/invoke.<br /><br />When I created the C++/CLI intermediate DLL, I had to use MSVC 2008 because it was difficult, and impossible for me to figure out how to get the target and plaform compiler correct for .NET 3.5 C++/CLI in MSVC 2015. I also had to deal with the fact that everything had to be x64<br /><br />My question is: in the native C++ file (which I'm building in MSVC 2015), using your example, how do I properly reference and include the intermediate C++/CLI dll so that I can make the call to fnInteropBridge ? And do I need to re-declare the "struct EventData" portion in the native C++ ?<br /><br />Thanks for your example and help.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-17960381844148625102016-05-13T11:17:52.770-04:002016-05-13T11:17:52.770-04:00Saurabh, Yes ManagedLib is the namespace for the r...Saurabh, Yes ManagedLib is the namespace for the referenced managed class in your .NET assembly. You will need to add reference to it from your C++ (with /clr option) project. If you have the ManagedLib project in the same Visual Studio solution, you can add a project reference from C++ project by right clicking "References" -> "Add Reference...", or you can do the file reference by browsing to the .NET assembly. There is something you need to watch out: the target .NET framework for the C++ project needs to match that of the .NET assembly being referenced. Follow the directions <a href="https://msdn.microsoft.com/en-us/library/ff770576.aspx" rel="nofollow">here</a> if you encounter this issue.<br /><br />Marshal is a managed type defined in System::Runtime::InteropServices; and IntPtr is in System namespace. <br /><br />Good luck!Hugh Anghttps://www.blogger.com/profile/09609747815666754891noreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-57155989272537328552016-05-13T03:37:40.401-04:002016-05-13T03:37:40.401-04:00I did try the COM interop path and it worked fine ...I did try the COM interop path and it worked fine too, unless there was an issue with the .NET version on which the .dll was build and the runtime where it was consumed, which eventually is a scary thing for my feature hence discarded that approach. Trying this reverse pinvoke way and have issue with the following two lines,<br /><br />ManagedLib::ManagedClass^ c = gcnew ManagedLib::ManagedClass();<br /><br />Here what is "ManagedLib", I understand the class is the C# class and expected this to be the namespace, but it refuses to compile in my project. Pls comment/help.<br /><br />IntPtr p = Marshal::GetFunctionPointerForDelegate(c->GetDelegate());<br /><br />Here the "Marshal" keyword is causing the issue, I believe this is a class too, but does this need any header file inclusion?<br />Saurabh Bansalhttps://www.blogger.com/profile/10744932010063645276noreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-68301561980032756562016-05-10T22:56:41.821-04:002016-05-10T22:56:41.821-04:00Saurabh, have you tried the approach from my blog ...Saurabh, have you tried the approach from my blog post? Another way to do it is wrap your C# code in COM, which then can be called from your C++.Hugh Anghttps://www.blogger.com/profile/09609747815666754891noreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-43274174572955944802016-05-10T06:05:48.982-04:002016-05-10T06:05:48.982-04:00I have requirement somewhat similar where I want t...I have requirement somewhat similar where I want to call a c# method directly from c++. How can I do it please help, in urgent need of support.Saurabh Bansalhttps://www.blogger.com/profile/10744932010063645276noreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-48289023491779059462013-03-30T01:57:04.166-04:002013-03-30T01:57:04.166-04:00Hello Hugh,
Thanks for the helpful post .
I have...Hello Hugh,<br /><br />Thanks for the helpful post .<br /><br />I have a manged DLL ( C++/CLI ) , which has also a wrapper of the C# library .<br /><br />Now I want to call the C++/CLI dll from a native C++ code. I want to get a pointer to the wrapper , from my C++ appliation , and would like to call the function , rather than exporting all the function.<br /><br />It shall be very helpful if you can provide an exampleSujay Ghoshhttps://www.blogger.com/profile/15173250657404685979noreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-35085100948296982342013-02-11T21:19:05.402-05:002013-02-11T21:19:05.402-05:00You have instructions with how to compile mixed mo...You have instructions with how to compile mixed mode dll using a c++ project application. Would you know if you can use mixed mode dll when your c++ is configured in a makefile? Specifically, adding the references?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-17206215842878393432013-01-30T21:24:21.080-05:002013-01-30T21:24:21.080-05:00I would love to have this code and the projects. I...I would love to have this code and the projects. I use VS 2008 and need to implement this same kind of approach. Please let me know where I can get the code.<br />Thanks for a wonderful article.<br />WyattAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-8507051984475108782012-04-03T08:35:48.061-04:002012-04-03T08:35:48.061-04:00It works!! Thank you again..It works!! Thank you again..Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-21760051764675792952012-03-24T09:59:49.407-04:002012-03-24T09:59:49.407-04:00Amit, you can add a reference to the C# project or...Amit, you can add a reference to the C# project or any .NET assembly from your C++ CLR project.<br /><br />HTHHugh Anghttps://www.blogger.com/profile/09609747815666754891noreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-75814123937667932522012-03-22T05:52:02.929-04:002012-03-22T05:52:02.929-04:00Hello,
Thank you very much for you helpful post!
...Hello,<br /><br />Thank you very much for you helpful post!<br /><br />I misunderstood something.<br /><br />In the CLR project (that connect between c# and c++). I cant see any connection to the c# project.<br /><br />you use the class: <br />ManagedLib::ManagedClass c = gcnew ManagedLib::ManagedClass();<br />but ManagedLib::ManagedClass is defined in the C# code and not in my CLR project.<br />do I have to add an include or somwthing else?<br /><br />thank you again :)<br /><br />AmitAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-1887270006101031992012-03-22T05:01:42.318-04:002012-03-22T05:01:42.318-04:00Thank you for this helpful information!
I tried t...Thank you for this helpful information!<br /><br />I tried to do everything you said, but I have a problem in the CLR project (that connect between c++ and c#..)<br /><br />you defined there:<br />ManagedLib::ManagedClass but it defined in the c# code so this class is not recognized!<br /><br />What should I do?<br /><br />thank you again!<br /><br />AmitAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-86562123269644079982009-02-04T16:35:00.000-05:002009-02-04T16:35:00.000-05:00Hi David, Thanks for your comments. I am glad that...Hi David, Thanks for your comments. I am glad that you found the post helpful. You were right that managed functions can be invoked directly by the C++/CLI code. I was exploring how to invoke .NET delegate from native code so I can bubble native "event" to all .NET listeners. I haven't tried this but it should work just fine if the delegate invoked by the C++/CLI code is chained.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-53293339839599920432009-01-21T05:21:00.000-05:002009-01-21T05:21:00.000-05:00Thanks for the post, it helped me solve a problem,...Thanks for the post, it helped me solve a problem, and you saved me countless hours by providing an easy example of how to do this.<BR/><BR/>One change I made was that I called a static method in the managed side, and I did not need a delegate; I just called the managed method directly. The C++/CLI runtime takes care of the details of marshaling the call from native-to-managed.<BR/><BR/><BR/>Also, you don't need to provide a delegate or special marshaling instructions to call from the mixed DLL to the pure managed DLL. <BR/><BR/>In other words, from the mixed mode DLL, rather than do this...<BR/> <B>ManagedClassProvider::ManagedClass^ c = gcnew ManagedClassProvider::ManagedClass();<BR/> IntPtr p = Marshal::GetFunctionPointerForDelegate(c->GetDelegate());<BR/> NativeToManaged funcPointer = (NativeToManaged) p.ToPointer();<BR/> funcPointer(data);<BR/></B><BR/><BR/>all I needed to do was this...<BR/><BR/><B><BR/> ManagedClass::ManagedClass^ c = gcnew ManagedClassProvider::ManagedClass();<BR/> ManagedClass::EventData data; // defined in managed dll<BR/> mdata.I = 50;<BR/> mdata.Message = gcnew String("Hello from Mixed Mode");<BR/> c->Trace(data);<BR/></B><BR/><BR/>...and it worked.<BR/><BR/>One thing that surprised me was that I did not need to host the CLR before calling into it. Apparently the C++/CLI runtime provides a default host and AppDomain (DefaultDomain) if the CLR is not already running, so it just worked.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-362796945673239800.post-19853512141596098552008-10-01T19:54:00.000-04:002008-10-01T19:54:00.000-04:00Thank you for the very helpful post.Thank you for the very helpful post.Anonymousnoreply@blogger.com