Click to See Complete Forum and Search --> : MFC DLL wrapper for C# GUI
DHarman
December 7th, 2009, 10:06 AM
I am completely new to C# programming and I'm having a hard time finding a tutorial on how to "wrap" existing MFC code for use in a C# app.
I have a current application written completely in C++ using MFC. The app is broken down into the GUI section and about 3 or 4 underlying MFC DLLs.
My current task is to use the existing underlying MFC DLLs with a C# .NET GUI. Based on what I've read, this is possible by wrapping the MFC DLLs...possibly in more than one wrapper? I just need to know...in simple terminology....how to do this?
The DLLs have individual functions exported. However, some of the exported functions take MFC parameters such as CList, CString, or structures containing CLists/CStrings, etc.
I'd really appreciate it if someone could explain in detail how to write the "wrappers" needed. If you've found a good detailed tutorial feel free to give the link. I just haven't been able to find one that is detailed enough for someone brand new to C# and the idea of wrappers.
Thanks
mattst
December 7th, 2009, 11:07 AM
Well this may not be exactly what you're looking for, it's not MFC for starters, but I needed to do something similar yesterday and used the code below. So this might help get you started, though others no doubt will provide better help.
Note Needs: using System.Runtime.InteropServices;
// Import function from a dll
[DllImport("kernel32.dll", EntryPoint = "SetSystemTime", SetLastError = true)]
public extern static bool Win32SetSystemTime(ref SystemTime sysTime);
// Define the SystemTime struct to be sent to the imported function.
public struct SystemTime
{
public ushort Year;
public ushort Month;
public ushort DayOfWeek;
public ushort Day;
public ushort Hour;
public ushort Minute;
public ushort Second;
public ushort Millisecond;
};
// Example usage
public void SetTime(DateTime dt)
{
SystemTime st;
st.Year = (ushort)dt.Year;
st.Month = (ushort)dt.Month;
st.DayOfWeek = (ushort)dt.DayOfWeek;
st.Day = (ushort)dt.Day;
st.Hour = (ushort)dt.Hour;
st.Minute = (ushort)dt.Minute;
st.Second = (ushort)dt.Second;
st.Millisecond = (ushort)dt.Millisecond;
Win32SetSystemTime(ref st);
}
Please note that I am fairly sure that the EntryPoint specifies the function name, in this case 'SetSystemTime', but the function declaration may have a user specified name (if you want) in this case 'Win32SetSystemTime' as long as the declaration types and the parameters are are all correct. I think this because kernel32.dll has no entry for 'Win32SetSystemTime' when I examined it but it does have 'SetSystemTime'.
Hope this helps.
DHarman
December 7th, 2009, 12:14 PM
Thanks for the example. I've implemented a few of the functions like that when they take parameters that can be marshaled.
My real issue deals with the MFC objects. If the exported function that I want to call takes a CList as a parameter (or a struct containing a CList) I need to know how to do that conversion. I've heard that I have to wrap the MFC DLL with a managed/unmanaged mixed DLL or something, but I don't really understand how to do that. Any other suggestions are appreciated.
Thanks again for trying to help.
BigEd781
December 7th, 2009, 12:36 PM
I realize that this does not address your question specifically, but do you really need to do this at all? You could probably port the C++ straight to C# and lose a lot of lines in the process. Why not just port directly to C#? What is the point of porting if you have to wrap a ton of code anyway?
mattst
December 7th, 2009, 12:44 PM
Oh I see !! Oops.
I didn't fully appreciate the problem. My experience with MFC was fairly limited and I last programmed using it over ten years ago, I'd say 1996 or 1997.
Have a look at this old thread - it's 4 pages about C# and MFC, I didn't read it but the discussion, which really gets going on page 2, might help you determine whether it's possible to do what you want. Asking your question in that thread might have some helpful responses if the users are still active.
"C# and mfc" thread here:
http://www.codeguru.com/forum/showthread.php?t=181518
HTH.
DHarman
December 7th, 2009, 12:51 PM
It's actually not a lot of code to port....at least I don't think it will be. In one DLL, there are 13 exported function calls. Of those 13, 4 of them can be imported directly and the parameters marshalled like this for example -
//C# file contains this
[DllImport("MyDLL.dll", EntryPoint="DoSomething")]
public static extern int DoSomething([MarshalAs UnmanagedType.LPTStr)]string c);
//for this exported MFC function
long DoSomething(CString c)
The 2nd DLL has only 2 functions which both take just ints...so no problem there (we can implement them like shown above). The 3rd DLL has 14 exported functions and 7 of those can be imported directly and the parameters marshalled (like above). The other 7 have void* as either the return or a parameter, so that will be my next question...how to handle void pointers. But for now I'm just looking for how to handle the MFC specific params like CList.
But to answer your question specifically, the application is very time sensitive and requires direct memory management. Plus since no one on our team is familiar with C# (we are currently learning) the learning curve would be too steep to rewrite all the DLLs plus the GUI logic in the timeframe we have. Thanks for the suggestion though.
DHarman
December 7th, 2009, 01:04 PM
Thanks for the link...I had actually run across that one when looking for a solution before my initial post. Those posts were from 2000 and sound like the discussion was before C# was as prevalent as it is now. Based on other threads I've read, some good points were made in the link you gave. I don't think you can go straight from MFC to C#. Instead you have to go through managed C++ somehow, then to C# from there. I just have no idea how and can't seem to find an example. The threads that mention to do that say just that...they don't give any detail and are several years old so I doubt anyone involved with the original thread is still monitoring it.
By the way, you said that the thread in the link you sent was 4 pages....I only see 2. Did you paste the correct link?
Any other ideas?
mattst
December 8th, 2009, 06:04 AM
By the way, you said that the thread in the link you sent was 4 pages....I only see 2. Did you paste the correct link?
Any other ideas?
Yes the correct link, I see 55 posts over 4 pages. I use the forum default number of posts to display per page, maybe you don't.
Other ideas - well I'd post in that thread, it's old but posters probably won't have removed email notification for replies and if they're still active here then their email address will be current. Worst case scenario - no replies.
I have no clue at all how to format the import code, or indeed if it's possible. You wrote in an earlier post that you don't have the time to port the code to C# in the time frame available. It might be worth re-thinking if development in C# is your best bet.
Zaccheus
December 8th, 2009, 11:35 AM
The DLLs have individual functions exported. However, some of the exported functions take MFC parameters such as CList, CString, or structures containing CLists/CStrings, etc.
I think that will prove to be pretty much impossible.
Just one example, those classes throw C++ exceptions.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.