none
exposing a C# DLL's members to non .NET apps RRS feed

  • Question

  • Hi, I posted this in another forum (slightly different question though) and the answers I recieved weren't very helpful. Basically, I need to create a C# DLL who's members can be accessed by a non .NET application (it's a Windows program called Extend). Now I was able to write one in C++ and have it's members be exposed using extern "C" int __declspec(dllexport), but so far have been unsuccessful in doing so in C#. Is it even possible?
    Tuesday, October 17, 2006 3:56 PM

Answers

All replies

  • I don't believe it is.  In order to call a method inside a C# class you'll have to start up the .NET runtime which might not even be running in the other app.  Furthermore even in C++ you can't really expose a C++ class member (which is all a C# method is) directly.  You had to expose the entire class (which was neither easy nor portable).  I think your best option is to write an intermediary binary that exposes global functions that can be called from unmanaged code and that uses your C# method through interop.  The easiest approach would probably be to use C++/CLI as you can create unmanaged global functions and still reference managed classes without any additional work.  In this case you'd write a C++/CLI binary that contains a global function for each piece of functionality you want to expose.  The global functions would use the C# class internally to implement the functionality.  IMHO.

    Note that this is part of the purpose of COM so if you can use COM then you can interact between unmanaged code and your C# class through COM.

    Michael Taylor - 10/17/06

    Tuesday, October 17, 2006 5:43 PM
    Moderator
  • Michael, thanks for the reply. I know you're a MVP and everything, but it is possible and relatively easy to expose individual members/methods in a C++ DLL. All I did was -

    //Extend.h
    class CExtendApp : public CWinApp
    {
    public:
        CExtendApp();
        __declspec(dllexport) int webAdd(int x,int y);
        __declspec(dllexport) void SendAMessage(char* msg);
        __declspec(dllexport) void SendInt(int i);
    ....

    //Extend.cpp
    CExtendApp::CExtendApp()
    {
        // TODO: add construction code here,
        // Place all significant initialization in InitInstance
    }


    extern "C" int __declspec(dllexport) CExtendApp::webAdd(int x, int y){
      ....
      ....
    }

    extern "C" void __declspec(dllexport) CExtendApp::SendInt(int i){
       ...
    }

    extern "C" void __declspec(dllexport) CExtendApp::SendAMessage(char* msg){
        ...
    }

    I was just wondering if there was anything as simple as that in C#. The reason I am asking is because now I need to access a web service and I sure it is much easier to do from C#. So far it seems like calling one from C++ is a bit complicated and I was hoping to find a fairly simple solution. Thanks for the help though. I think you answered my question.
    Tuesday, October 17, 2006 6:04 PM
  • AFAIK there is no way to create a true global function in C# (although .NET itself supports it).  Your best bet is to use C++/CLI to do it.  In this case you'd create a simple C++/CLI dll that contained a global function for each operation you wanted to expose.  You would then use your C# class inside the dll to invoke the web service and whatnot.  Note that if you use C++/CLI then you actually have full access to the .NET framework so it might be just as easy to write the web service code in C++/CLI.  Nevertheless assuming the following C# code:

    public class CallMyWebService
    {
       public CallMyWebService ( ) { }

       public void CallWebService ( ) { }
    }

    //In a C++/CLI dll
    extern "C" __declspec(dllexport) void CallWebService ( )
    {
       CallMyWebService^ ws = new CallMyWebService();
       ws->CallWebService();
    }

    //In your client code
    ...
    CallWebService();
    ...

    Not 100% sure on the C++/CLI syntax but the gist is that you create an instance of the C# web service in the C++/CLI dll (perhaps storing it in a class member variable) and then just expose global functions to call the methods on the class.  This will get sort of tedious.  Alternatively you could create a class and expose methods on it but that gets ugly real fast.  For unmanaged function calls you are best to stick with global functions.

    Michael Taylor - 10/17/06

    Tuesday, October 17, 2006 6:29 PM
    Moderator
  • It is prefectly ok to do so.

    Although you need a wrapper class.  Actually, I asked a similar question in the C++ forum a few days ago because I have a similar problem.  The folks there provided me a solution which use gcroot.

    Below is the link

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=822738&SiteID=1

     


     

    Tuesday, October 17, 2006 6:56 PM
  • See these Articles:

    http://www.codeproject.com/csharp/ManagedCOM.asp

    http://www.codeproject.com/dotnet/bridge.asp

    There are some limitations of types which are supported by .Net but not the old Platforms. So you have to be a little bit choosy when you are writing some component in .Net which needs to be accessed from unmanaged language like VB and C++. Further, You cant get rid of .Net framework by default.

    If you also need to embed .Net Libraries with you component, then try Xenocode Post Build.

    Best Regards ;-),

    Tuesday, October 17, 2006 7:52 PM
  • Hi pappascd:

    Although very restrictive, I have succeeded in years past in exposing a subset of native methods from a VC++ class with __declspec(dllexport) without exporting all the members of a class.  This is the poor man's way of exposing an interface without creating a separate interface class.  However, it should be said that this is restricted to a purely VC++ environment, and in some cases restricted by compiler because of mangled code differences in C++.  From my recollection, in VC++ you can even alter the default calling convention on methods.  However, again, you cannot strip the mangled naming information from the method to effectively make the method a "C" call supported as accessible by other languages.

    TaylorMichaelL is right on the money when it come to using COM (CCW) and "It-Just-Works" (IJW) managed extensions(C++/CLI).

    There are some very difficult paths with COM Interop such as working with mult-dimensional arrays or in passing a record within a variant from managed code to native code.  In the latter case, one has to create a custom Variant structure in managed code as a workaround because it does not exist in managed code.  And, lets not forget difficulties in working with nested structures.  COM does, however, support certain things like declarative and programmatic launch/access security permissions.  Another plus for COM is that companies have written bridges from COM to CORBA and J2EE.  This might prove beneficial to some.

    Some of the things that are now steering me away from COM towards IJW and C++/CLI include greater ease with marshaling data between native and managed code environments.  Exception handling also becomes a great deal easier.  You no longer need _com_error exception handling using ICreateErrorInfo, IErrorInfo, ISupportErrorInfo and APIs ::GetErrorInfo() and :SetErrorInfo(); however, one can say that COM exception handling is robust and can provide significant information for the user or for logging purposes.

    On my current assignment, both of these technologies, COM and C++/CLI, are in use or have been implemented towards the release of our next product.  These are helping to bridge the gap between VC# and legacy VC++ applications where certain VC++ legacy project subsystems have been recompiled from VC++ 6.0 to VC 8.0.  Even communication socket bridges with TCP/IP between managed and native code have been used.  However, interestingly enough, no .NET Remoting has been used at all in relation to network support needs even though the new product is entirely built within in a Microsoft networking multi-tier/platform environment.  PINVOKE is used in some cases where needed and possible; this is used for cases of simple access from VC# managed code to 'C' calls in an API C-supported DLL.

    I hope I have added some value to your decision making or considerations.

    James Sigler - 10-17-2006

    Dallas, TX

    jmsigler2@hotmail.com

    Wednesday, October 18, 2006 3:37 AM