Click here to Skip to main content
15,893,663 members
Home / Discussions / C#
   

C#

 
GeneralRe: Strange problem with ownerdraw listbox Pin
Heath Stewart23-Mar-04 13:56
protectorHeath Stewart23-Mar-04 13:56 
GeneralRe: Strange problem with ownerdraw listbox Pin
Anders Molin23-Mar-04 14:00
professionalAnders Molin23-Mar-04 14:00 
GeneralRe: Strange problem with ownerdraw listbox Pin
Anders Molin23-Mar-04 14:16
professionalAnders Molin23-Mar-04 14:16 
GeneralSerialization Pin
Not Active23-Mar-04 10:06
mentorNot Active23-Mar-04 10:06 
GeneralRe: Serialization Pin
Heath Stewart23-Mar-04 10:37
protectorHeath Stewart23-Mar-04 10:37 
GeneralRe: Serialization Pin
Not Active23-Mar-04 10:48
mentorNot Active23-Mar-04 10:48 
GeneralC#->C++ Interface Issue - Passing Data Pin
Chris_Lutz23-Mar-04 7:58
Chris_Lutz23-Mar-04 7:58 
GeneralRe: C#->C++ Interface Issue - Passing Data Pin
Heath Stewart23-Mar-04 9:04
protectorHeath Stewart23-Mar-04 9:04 
You could make an unmanaged interface which CGraphicsOptions would implement as a COM object. Declare this interface using the appropriate GuidAttribute and InterfaceTypeAttribute. If this interface was exposed in a typelib, you could simply use tlbimp.exe (or VS.NET can do it when you add a COM reference to your project) to create an interop assembly (RCW, Runtime Callable Wrapper). That would be one way.

The reason the interface would have to be a COM interface is because casting to an interface causes the CLR to QI (QueryInterface) for the interface. Your class's implementation of QueryInterface (ATL encapsulate all this nicely, BTW) returns a pointer to the class that implements that interface (most likely the class being QI'd) which the CLR treats as a reference to that interface.

The class wouldn't even necessarily have to be registered. So long as your C++ app's class factory creates a valid instance of it, you wouldn't even need a COM class factory (that which implements IClassFactory), so long as the managed code could get a reference to it even if all it does is use a pointer (see the Marshal class documentation to find easy ways to QI for an interface from an IntPtr).

Finally, there's always the ThisCall calling convention. If you export your CGraphicsOptions class in your native DLL, you need to create a class factory to create and destroy your class, but then declare managed methods using DllImportAttribute and the CallingConvention.ThisCall value for the DllImportAttribute.CallingConvention property.

So, besides exporting your class from the native DLL, also export your class factory functions:
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) LPVOID /* (void*) */ CreateGOClass();
__declspec(dllexport) void DestroyGOClass(LPVOID lpClass);
#ifdef __cplusplus
}
#endif
Using the CallingConvention.ThisCall convention, you pass a pointer to your class instances as the first parameter, so each would have an IntPtr as the first param. Your methods would be declared like so:
[DllImport("mylib.dll")]
private static extern IntPtr CreateGOClass();
[DllImport("mylib.dll")]
private static extern void DestroyGOClass(IntPtr inst);
[DllImport("mylib.dll", CallingConvention=CallingConvention.ThisCall)]
private static extern void SomeMethod(IntPtr inst, int param1, int param2);
For a good OO design, encapsulate all this in a singleton class that implements IDisposable. In the constructor, call CreateGOClass() to get the pointer and in Dispose call DestroyGOClass:
public sealed class GraphicsOptions : IDisposable
{
  private static GraphicsOptions instance;
  private IntPtr inst;
  private GraphicsOptions()
  {
    inst = CreateGOClass();
  }
  private static GraphicsOptions Instance
  {
    get
    {
      if (instance == null)
        lock (typeof(GraphicsOptions))
          if (instance == null)
            instance = new GraphicsOptions();
      return instance;
    }
  }
  public static void SomeMethod(int param1, int param2)
  {
    SomeMethod(Instance.inst, param1, param2);
  }
  void IDisposable.Dispose()
  {
    DestroyGOClass(inst);
    GC.SuppressFinalize(this);
  }
  [DllImport("mylib.dll")]
  private static extern IntPtr CreateGOClass();
  [DllImport("mylib.dll")]
  private static extern void DestroyGOClass(IntPtr inst);
  [DllImport("mylib.dll", CallingConvention=CallingConvention.ThisCall)]
  private static extern void SomeMethod(IntPtr inst, int param1, int param2);
}
Then all you have to do to call it is:
GraphicsOptions.SomeMethod(1, 2);
It wouldn't have to be a singleton, though. I just did so because you mentioned something along those lines in your request for ideas.

 

Microsoft MVP, Visual C#
My Articles
GeneralDetect new running process Pin
Apusnaias23-Mar-04 5:53
Apusnaias23-Mar-04 5:53 
GeneralRe: Detect new running process Pin
Dave Kreskowiak23-Mar-04 6:12
mveDave Kreskowiak23-Mar-04 6:12 
GeneralRe: Detect new running process Pin
Heath Stewart23-Mar-04 9:16
protectorHeath Stewart23-Mar-04 9:16 
GeneralRe: Detect new running process Pin
Apusnaias23-Mar-04 11:22
Apusnaias23-Mar-04 11:22 
GeneralRe: Detect new running process Pin
Dave Kreskowiak23-Mar-04 11:46
mveDave Kreskowiak23-Mar-04 11:46 
GeneralRe: Detect new running process Pin
Apusnaias23-Mar-04 23:30
Apusnaias23-Mar-04 23:30 
GeneralRe: Detect new running process Pin
ian mariano23-Mar-04 11:20
ian mariano23-Mar-04 11:20 
GeneralRe: Detect new running process Pin
Robert M Greene26-Oct-04 7:39
Robert M Greene26-Oct-04 7:39 
GeneralGraphics.MeasureString Pin
compbssn200323-Mar-04 5:30
compbssn200323-Mar-04 5:30 
GeneralRe: Graphics.MeasureString Pin
Heath Stewart23-Mar-04 5:33
protectorHeath Stewart23-Mar-04 5:33 
GeneralRe: Graphics.MeasureString Pin
leppie23-Mar-04 6:06
leppie23-Mar-04 6:06 
GeneralRe: Graphics.MeasureString Pin
compbssn200323-Mar-04 19:20
compbssn200323-Mar-04 19:20 
GeneralExposing constituent control properties in VS.NET Pin
Matt Davison23-Mar-04 5:07
Matt Davison23-Mar-04 5:07 
GeneralRe: Exposing constituent control properties in VS.NET Pin
Heath Stewart23-Mar-04 5:30
protectorHeath Stewart23-Mar-04 5:30 
GeneralRe: Exposing constituent control properties in VS.NET Pin
Heath Stewart23-Mar-04 8:16
protectorHeath Stewart23-Mar-04 8:16 
QuestionHow can I do the following... Pin
profoundwhispers23-Mar-04 4:36
profoundwhispers23-Mar-04 4:36 
AnswerRe: How can I do the following... Pin
Heath Stewart23-Mar-04 4:54
protectorHeath Stewart23-Mar-04 4:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.