none
Referencing a DLL ATL project from C# RRS feed

  • Question

  • Hi,

    Using VS2005 I have created a DLL ATL project.
    I built the project.
    Then I opened a new instance of Visual Studio, and I created a C# console application.
    I clicked 'Add References ...". Under the COM tab the DLL that I had created previously was shown.
    Then I added this ATL DLL as a reference to my C# project.

    My question is why does not appear a corresponding namespace in my C# code after performing the mentioned operations?
    Which operation did I miss to do?

    Thx for any suggestion.
    Monday, July 13, 2009 12:20 PM

Answers

  • Add the methods to one of the interfaces implemented by your class, for example SayHello to IMyClass interface :

    definition (in the IDL file):

    interface IMyClass {
      HRESULT SayHello([out] BSTR *msg);
    }

    implementation (in the CPP file):
    STDMETHOD  SayHello(/*out*/ BSTR *msg)
    {
        *msg = ::SysAllocString(L"Hello");
        return S_OK;
    }

    and in your C# code just call the method:

    MyClass obj = new MyClass();
    Console.WriteLine(obj.SayHello());
    • Marked as answer by vmware Tuesday, July 14, 2009 11:23 AM
    Monday, July 13, 2009 4:30 PM
  • No idea what "lots of error messages" means.  Pba forgot the line you need to add to the .h file to declare the SayHello member.

    Hans Passant.
    • Marked as answer by vmware Tuesday, July 14, 2009 11:23 AM
    Monday, July 13, 2009 5:44 PM
    Moderator

All replies

  • If adding the COM reference worked, you've got a namespace for the classes in the interop library.  It is normally the same as the name of the reference as it appears in the References node of your project.  Right click it and choose View in Object Browser to have a look-see.

    Hans Passant.
    Monday, July 13, 2009 2:37 PM
    Moderator
  • After adding a class to the C++ project, the namespace appears within C#.

    But my main objective is to make some very little app that does something, and what I cannot find is where to put functions that I would like to implement?

    Suppose I'd like to create a function like this:
    char *SayHello(void)
    {
      return "hello";
    }
    


    How/where should I integrate this function within the two files that VS added when I got it to add a class to the solution?

    MyClass.h added by Visual Studio
    // MyClass.h: Definition of the MyClass class
    //
    //////////////////////////////////////////////////////////////////////
    
    #if !defined(AFX_MYCLASS_H__935A8540_F09B_42FE_A94E_55F23C1B25FD__INCLUDED_)
    #define AFX_MYCLASS_H__935A8540_F09B_42FE_A94E_55F23C1B25FD__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    #include "resource.h"       // main symbols
    
    /////////////////////////////////////////////////////////////////////////////
    // MyClass
    
    class MyClass : 
    	public IDispatchImpl<IMyClass, &IID_IMyClass, &LIBID_SAMPLEATLCOMAPPLib>, 
    	public ISupportErrorInfo,
    	public CComObjectRoot,
    	public CComCoClass<MyClass,&CLSID_MyClass>
    {
    public:
    	MyClass() {}
    BEGIN_COM_MAP(MyClass)
    	COM_INTERFACE_ENTRY(IDispatch)
    	COM_INTERFACE_ENTRY(IMyClass)
    	COM_INTERFACE_ENTRY(ISupportErrorInfo)
    END_COM_MAP()
    //DECLARE_NOT_AGGREGATABLE(MyClass) 
    // Remove the comment from the line above if you don't want your object to 
    // support aggregation. 
    
    DECLARE_REGISTRY_RESOURCEID(IDR_MyClass)
    // ISupportsErrorInfo
    	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
    
    // IMyClass
    public:
    };
    
    #endif // !defined(AFX_MYCLASS_H__935A8540_F09B_42FE_A94E_55F23C1B25FD__INCLUDED_)
    

     MyClass.cpp added by Visual Studio

    // MyClass.cpp : Implementation of CSampleAtlComAppApp and DLL registration.
    
    #include "stdafx.h"
    #include "SampleAtlComApp.h"
    #include "MyClass.h"
    
    /////////////////////////////////////////////////////////////////////////////
    //
    
    STDMETHODIMP MyClass::InterfaceSupportsErrorInfo(REFIID riid)
    {
    	static const IID* arr[] = 
    	{
    		&IID_IMyClass,
    	};
    
    	for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
    	{
    		if (InlineIsEqualGUID(*arr[i],riid))
    			return S_OK;
    	}
    	return S_FALSE;
    }
    Thx.
    Monday, July 13, 2009 3:04 PM
  • Add the methods to one of the interfaces implemented by your class, for example SayHello to IMyClass interface :

    definition (in the IDL file):

    interface IMyClass {
      HRESULT SayHello([out] BSTR *msg);
    }

    implementation (in the CPP file):
    STDMETHOD  SayHello(/*out*/ BSTR *msg)
    {
        *msg = ::SysAllocString(L"Hello");
        return S_OK;
    }

    and in your C# code just call the method:

    MyClass obj = new MyClass();
    Console.WriteLine(obj.SayHello());
    • Marked as answer by vmware Tuesday, July 14, 2009 11:23 AM
    Monday, July 13, 2009 4:30 PM
  • It doesn't work. I get lots of error messages.

    Before pasting these few lines of code should I have added a new class
    - of type
        (a) generic or
        (b) ATL?
    - with an interface type
        (a) dual or
        (b) custom?
    Monday, July 13, 2009 4:51 PM
  • No idea what "lots of error messages" means.  Pba forgot the line you need to add to the .h file to declare the SayHello member.

    Hans Passant.
    • Marked as answer by vmware Tuesday, July 14, 2009 11:23 AM
    Monday, July 13, 2009 5:44 PM
    Moderator
  • I could not make it work.

    This is my source code for the 3 files after adding an 'ATL class with a dual interface'.

    Could you tell me at which line I should insert the 3 additional code fragements?

    MyClass.cpp
    00 // MyClass.cpp : Implementation of CAtlComSampleApp and DLL registration.
    01
    02 #include "stdafx.h"
    03 #include "AtlComSample.h"
    04 #include "MyClass.h"
    05
    06 /////////////////////////////////////////////////////////////////////////////
    07 //
    08
    09 STDMETHODIMP MyClass::InterfaceSupportsErrorInfo(REFIID riid)
    10 { 
    11 	static const IID* arr[] = 
    12 	{
    13 		&IID_IMyClass,
    14 	};
    15 
    16 	for (int i=0;i
    

    MyClass.h
    00 // MyClass.h: Definition of the MyClass class
    01 //
    02 //////////////////////////////////////////////////////////////////////
    03
    04 #if !defined(AFX_MYCLASS_H__ACE63916_3455_4E1B_B465_4C12C3337327__INCLUDED_)
    05 #define AFX_MYCLASS_H__ACE63916_3455_4E1B_B465_4C12C3337327__INCLUDED_
    06
    07 #if _MSC_VER > 1000
    08 #pragma once
    09 #endif // _MSC_VER > 1000
    10
    11 #include "resource.h"       // main symbols
    12
    13 /////////////////////////////////////////////////////////////////////////////
    14 // MyClass
    15 
    16 class MyClass : 
    17 	public IDispatchImpl, 
    18 	public ISupportErrorInfo,
    19 	public CComObjectRoot,
    20 	public CComCoClass
    21 {
    22 public:
    23 	MyClass() {}
    24 BEGIN_COM_MAP(MyClass)
    25 	COM_INTERFACE_ENTRY(IDispatch)
    26 	COM_INTERFACE_ENTRY(IMyClass)
    27 	COM_INTERFACE_ENTRY(ISupportErrorInfo)
    28 END_COM_MAP()
    29 //DECLARE_NOT_AGGREGATABLE(MyClass) 
    30 // Remove the comment from the line above if you don't want your object to 
    31 // support aggregation. 
    32
    33 DECLARE_REGISTRY_RESOURCEID(IDR_MyClass)
    34 // ISupportsErrorInfo
    35 	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
    36
    37 // IMyClass
    38 public:
    39 };
    40 
    41 #endif // !defined(AFX_MYCLASS_H__ACE63916_3455_4E1B_B465_4C12C3337327__INCLUDED_)
    


    AtlComSample.idl
    00 // AtlComSample.idl : IDL source for AtlComSample.dll
    01 //
    02
    03 // This file will be processed by the MIDL tool to
    04 // produce the type library (AtlComSample.tlb) and marshalling code.
    05
    06 import "oaidl.idl";
    07 import "ocidl.idl";
    08	
    09 	[
    10 		object,
    11 		uuid(7BD35282-50E2-43EC-9456-BDC5795BC0F5),
    12 		dual,
    13 		helpstring("IMyClass Interface"),
    14 		pointer_default(unique)
    15 	]
    16 	interface IMyClass : IDispatch
    17 	{
    18 	};
    19
    20 [
    21 	uuid(9D3A397C-F890-41B4-A00D-0B6EA3ECFED4),
    22 	version(1.0),
    23 	helpstring("AtlComSample 1.0 Type Library")
    24 ]
    25 library ATLCOMSAMPLELib
    26 {
    27 	importlib("stdole32.tlb");
    28 	importlib("stdole2.tlb");
    29 
    30 	
    31 	[
    32 		uuid(8E0DA051-424A-45FC-8B65-096929D1BB1D),
    33 		helpstring("MyClass Class")
    34 	]
    35 	coclass MyClass
    36 	{
    37 		[default] interface IMyClass;
    38 	};
    39 };
    
    Tuesday, July 14, 2009 8:33 AM
  • 9, 39 and 38.

    Hans Passant.
    Tuesday, July 14, 2009 9:44 AM
    Moderator
  • I get these two error messages:

    SampleApplication.idl(39) : error MIDL2025 : syntax error : expecting DispatchInterfaceName or an interface name near "HRESULT"
    SampleApplication.idl(39) : error MIDL2026 : cannot recover from earlier syntax errors; aborting compilation

    // SampleApplication.idl : IDL source for SampleApplication.dll
    //
    
    // This file will be processed by the MIDL tool to
    // produce the type library (SampleApplication.tlb) and marshalling code.
    
    import "oaidl.idl";
    import "ocidl.idl";
    	
    	[
    		object,
    		uuid(51DC6420-73E8-4473-A16A-A52FDB419A80),
    		dual,
    		helpstring("IMyClass Interface"),
    		pointer_default(unique)
    	]
    	interface IMyClass : IDispatch
    	{
    	};
    
    [
    	uuid(3170E3F2-F62A-4FED-9E62-D37CF234F222),
    	version(1.0),
    	helpstring("SampleApplication 1.0 Type Library")
    ]
    library SAMPLEAPPLICATIONLib
    {
    	importlib("stdole32.tlb");
    	importlib("stdole2.tlb");
    
    	
    	[
    		uuid(C50839A0-616A-43A6-91C1-60764C6D1861),
    		helpstring("MyClass Class")
    	]
    	coclass MyClass
    	{
    		[default] interface IMyClass;
    		HRESULT SayHello([out] BSTR *msg);
    	};
    };
    


    // MyClass.cpp : Implementation of CSampleApplicationApp and DLL registration.
    
    #include "stdafx.h"
    #include "SampleApplication.h"
    #include "MyClass.h"
    
    /////////////////////////////////////////////////////////////////////////////
    //
    
    STDMETHODIMP MyClass::SayHello(/*out*/ BSTR *msg)
    {
        *msg = ::SysAllocString(L"Hello");
        return S_OK;
    }
    
    STDMETHODIMP MyClass::InterfaceSupportsErrorInfo(REFIID riid)
    {
    	static const IID* arr[] = 
    	{
    		&IID_IMyClass,
    	};
    
    	for (int i=0;<sizeof(arr)/sizeof(arr[0]);i++)
    	{
    		if (InlineIsEqualGUID(*arr[i],riid))
    			return S_OK;
    	}
    	return S_FALSE;
    }
    
    


    // MyClass.h: Definition of the MyClass class
    //
    //////////////////////////////////////////////////////////////////////
    
    #if !defined(AFX_MYCLASS_H__8839E31B_EFC8_4E50_AC73_86C2EEC8FA7F__INCLUDED_)
    #define AFX_MYCLASS_H__8839E31B_EFC8_4E50_AC73_86C2EEC8FA7F__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    #include "resource.h"       // main symbols
    
    /////////////////////////////////////////////////////////////////////////////
    // MyClass
    
    class MyClass : 
    	public IDispatchImpl<IMyClass, &IID_IMyClass, &LIBID_SAMPLEAPPLICATIONLib>, 
    	public ISupportErrorInfo,
    	public CComObjectRoot,
    	public CComCoClass<MyClass,&CLSID_MyClass>
    {
    public:
    	MyClass() {}
    BEGIN_COM_MAP(MyClass)
    	COM_INTERFACE_ENTRY(IDispatch)
    	COM_INTERFACE_ENTRY(IMyClass)
    	COM_INTERFACE_ENTRY(ISupportErrorInfo)
    END_COM_MAP()
    //DECLARE_NOT_AGGREGATABLE(MyClass) 
    // Remove the comment from the line above if you don't want your object to 
    // support aggregation. 
    
    DECLARE_REGISTRY_RESOURCEID(IDR_MyClass)
    // ISupportsErrorInfo
    	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
    
    // IMyClass
    public:
    	STDMETHOD(SayHello)(BSTR *msg)
    };
    
    #endif // !defined(AFX_MYCLASS_H__8839E31B_EFC8_4E50_AC73_86C2EEC8FA7F__INCLUDED_)
    Tuesday, July 14, 2009 10:32 AM
  • Don't add it to the coclass, add it to the interface.

    Hans Passant.
    Tuesday, July 14, 2009 10:38 AM
    Moderator
  • Thank you so much, it works now.

    Here is the final code:

    // MyClass.cpp : Implementation of CSampleApplicationApp and DLL registration.
    
    #include "stdafx.h"
    #include "SampleApplication.h"
    #include "MyClass.h"
    
    /////////////////////////////////////////////////////////////////////////////
    //
    
    STDMETHODIMP MyClass::SayHello(/*out*/ BSTR *msg)
    {
        *msg = ::SysAllocString(L"hello from COM");
        return S_OK;
    }
    
    STDMETHODIMP MyClass::InterfaceSupportsErrorInfo(REFIID riid)
    {
    	static const IID* arr[] = 
    	{
    		&IID_IMyClass,
    	};
    
    	for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
    	{
    		if (InlineIsEqualGUID(*arr[i],riid))
    			return S_OK;
    	}
    	return S_FALSE;
    }
    // SampleApplication.cpp : Implementation of DLL Exports.
    
    
    // Note: Proxy/Stub Information
    //      To build a separate proxy/stub DLL, 
    //      run nmake -f SampleApplicationps.mk in the project directory.
    
    #include "stdafx.h"
    #include "resource.h"
    #include <initguid.h>
    #include "SampleApplication.h"
    
    #include "SampleApplication_i.c"
    #include "MyClass.h"
    
    
    CComModule _Module;
    
    BEGIN_OBJECT_MAP(ObjectMap)
    OBJECT_ENTRY(CLSID_MyClass, MyClass)
    END_OBJECT_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // DLL Entry Point
    
    extern "C"
    BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
    {
        if (dwReason == DLL_PROCESS_ATTACH)
        {
            _Module.Init(ObjectMap, hInstance, &LIBID_SAMPLEAPPLICATIONLib);
            DisableThreadLibraryCalls(hInstance);
        }
        else if (dwReason == DLL_PROCESS_DETACH)
            _Module.Term();
        return TRUE;    // ok
    }
    
    /////////////////////////////////////////////////////////////////////////////
    // Used to determine whether the DLL can be unloaded by OLE
    
    STDAPI DllCanUnloadNow(void)
    {
        return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
    }
    
    /////////////////////////////////////////////////////////////////////////////
    // Returns a class factory to create an object of the requested type
    
    STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
    {
        return _Module.GetClassObject(rclsid, riid, ppv);
    }
    
    /////////////////////////////////////////////////////////////////////////////
    // DllRegisterServer - Adds entries to the system registry
    
    STDAPI DllRegisterServer(void)
    {
        // registers object, typelib and all interfaces in typelib
        return _Module.RegisterServer(TRUE);
    }
    
    /////////////////////////////////////////////////////////////////////////////
    // DllUnregisterServer - Removes entries from the system registry
    
    STDAPI DllUnregisterServer(void)
    {
        return _Module.UnregisterServer(TRUE);
    }
    // MyClass.h: Definition of the MyClass class
    //
    //////////////////////////////////////////////////////////////////////
    
    #if !defined(AFX_MYCLASS_H__8839E31B_EFC8_4E50_AC73_86C2EEC8FA7F__INCLUDED_)
    #define AFX_MYCLASS_H__8839E31B_EFC8_4E50_AC73_86C2EEC8FA7F__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    #include "resource.h"       // main symbols
    
    /////////////////////////////////////////////////////////////////////////////
    // MyClass
    
    class MyClass : 
    	public IDispatchImpl<IMyClass, &IID_IMyClass, &LIBID_SAMPLEAPPLICATIONLib>, 
    	public ISupportErrorInfo,
    	public CComObjectRoot,
    	public CComCoClass<MyClass,&CLSID_MyClass>
    {
    public:
    	MyClass() {}
    BEGIN_COM_MAP(MyClass)
    	COM_INTERFACE_ENTRY(IDispatch)
    	COM_INTERFACE_ENTRY(IMyClass)
    	COM_INTERFACE_ENTRY(ISupportErrorInfo)
    END_COM_MAP()
    //DECLARE_NOT_AGGREGATABLE(MyClass) 
    // Remove the comment from the line above if you don't want your object to 
    // support aggregation. 
    
    DECLARE_REGISTRY_RESOURCEID(IDR_MyClass)
    // ISupportsErrorInfo
    	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
    
    // IMyClass
    public:
    	STDMETHOD(SayHello)(BSTR *msg);
    };
    
    #endif // !defined(AFX_MYCLASS_H__8839E31B_EFC8_4E50_AC73_86C2EEC8FA7F__INCLUDED_)
    Tuesday, July 14, 2009 11:21 AM