| 
		
	
	
	
		
	Posts: 133Threads: 15
 Joined: Jun 2014
 
	
	
		Hi Gintaras, 
I've defined a DLL in C++ with the following header:
 
Macro Macro108 // Math.h
 #ifdef MATH_EXPORTS
 #define MATH_API __declspec(dllexport)
 #else
 #define MATH_API __declspec(dllimport)
 #endif
 
 namespace Math
 {
 ,// This class is exported from the Math.dll
 ,class MathFuncs
 ,{
 ,,public:
 ,,// Returns a + b
 ,,static MATH_API double Add(double a, double b);
 ,,
 ,,// Returns a - b
 ,,static MATH_API double Subtract(double a, double b);
 ,,
 ,,// Returns a * b
 ,,static MATH_API double Multiply(double a, double b);
 ,,
 ,,// Returns a / b
 ,,// Throws const std::invalid_argument& if b is 0
 ,,static MATH_API double Divide(double a, double b);
 ,};
 }
What is the proper syntax to call it using QM?
 
Note: the DLL file name is "Math.dll"
	 
	
	
	
		
	Posts: 12,239Threads: 144
 Joined: Dec 2002
 
	
	
		Exported class function names will be decorated. Open your dll file with depends.exe and copy the decorated name. QM code could be: 
Macro Macro2345 dll "$qm$\math.dll" [?Add@Math@@YANNN@Z]double'Math_Add double'a double'bout Math_Add(5.7 2)
To avoid decoration, export non-class functions. Use either .def file or extern "C".
 
Or use a COM interface, especially when want to export non-static class functions.
	 
	
	
	
		
	Posts: 133Threads: 15
 Joined: Jun 2014
 
	
	
		Thank you very much. Now I know more about the decoration thing. On my machine it will look like this: 
Macro Macro106 dll "$my qm$\Dll\Math.dll" [?Add@MathFuncs@Math@@SANNN@Z]double'Math_Add double'a double'bout Math_Add(8.7 2)
 
	
	
	
		
	Posts: 133Threads: 15
 Joined: Jun 2014
 
	
	
		Could you give me a simple example just for "Add" function using:1/ extern "C"
 2/ COM interface
 
	
	
	
		
	Posts: 12,239Threads: 144
 Joined: Dec 2002
 
	
	
		Macro Macro2345 //Put this before a non-class function declaration and definition to export the function with __cdecl calling convention. It is the easiest way, don't need a .def file. Using Microsoft Visual C++.#define EXPORTC extern "C" __declspec(dllexport)
 
 namespace Math
 {
 ,class MathFuncs
 ,{
 ,,public:
 ,,// Returns a + b
 ,,static double Add(double a, double b);
 ,};
 
 ,double MathFuncs::Add(double a, double b) { return a+b; }
 
 EXPORTC
 double Math_Add(double a, double b) { return MathFuncs::Add(a, b); }
 }
With COM interface more work. If don't need to export non-static class members, better use extern "C".
	 
	
	
	
		
	Posts: 12,239Threads: 144
 Joined: Dec 2002
 
	
	
		To export static class or non-class functions also can be used this. But such functions can be used only in QM. 
Macro Macro2345 //Put this before a non-class function declaration and definition to export the function with __cdecl calling convention. It is the easiest way, don't need a .def file. Using Microsoft Visual C++.#define EXPORTC extern "C" __declspec(dllexport)
 
 namespace Math
 {
 ,class MathFuncs
 ,{
 ,,public:
 ,,// Returns a + b
 ,,static double Add(double a, double b);
 ,,static double Sub(double a, double b);
 ,};
 
 ,double MathFuncs::Add(double a, double b) { return a+b; }
 ,double MathFuncs::Sub(double a, double b) { return a-b; }
 
 ,const int mathFunctions[]=
 ,{
 ,,(int)MathFuncs::Add,
 ,,(int)MathFuncs::Sub,
 ,};
 
 EXPORTC
 const int* Math_GetFunctions() { return mathFunctions; }
Macro Macro2345 dll- "my.dll",int*Math_GetFunctions
 ,double'Math_Add double'a double'b
 ,double'Math_Sub double'a double'b
 
 int+* mathFunctions
 if !mathFunctions
 ,mathFunctions=Math_GetFunctions
 ,&Math_Add=mathFunctions[0]
 ,&Math_Sub=mathFunctions[1]
 
 out Math_Add(5.7 2)
 out Math_Sub(5.7 2)
 
	
	
	
		
	Posts: 12,239Threads: 144
 Joined: Dec 2002
 
	
	
		COM interface. 
Macro Macro2345 //Put this before a non-class function declaration and definition to export the function with __cdecl calling convention. It is the easiest way, don't need a .def file. Using Microsoft Visual C++.#define EXPORTC extern "C" __declspec(dllexport)
 
 //I use this C macro to implement IUnknown functions QueryInterface, AddRef and Release that support standard reference counting.
 //Can be used in any class that implements a COM interface. Example: STANDARD_IUNKNOWN_METHODS(IMyInterface)
 #define STANDARD_IUNKNOWN_METHODS(iface) \
 STDMETHODIMP QueryInterface(REFIID iid, void** ppv)\
 {\
 ,if(iid == IID_IUnknown || iid == IID_##iface) { m_cRef++; *ppv = this; return S_OK; }\
 ,else { *ppv = 0; return E_NOINTERFACE; }\
 }\
 STDMETHODIMP_(ULONG) AddRef()\
 {\
 ,return ++m_cRef;\
 }\
 STDMETHODIMP_(ULONG) Release()\
 {\
 ,long ret=--m_cRef;\
 ,if(!ret) delete this;\
 ,return ret;\
 }
 
 namespace Math
 {
 ,#define IID_IMathFuncs __uuidof(IMathFuncs)
 ,__interface __declspec(uuid("1DD0DD58-59C7-4308-93B8-40EEDEDE2415")) //replace this with your generated GUID
 ,IMathFuncs :public IUnknown
 ,{
 ,,STDMETHODIMP Add(double a, double b, double& R);
 ,,STDMETHODIMP Sub(double a, double b, double& R);
 ,};
 
 ,class MathFuncs :public IMathFuncs
 ,{
 ,,long m_cRef;
 ,,public:
 ,,MathFuncs() { m_cRef=1; }
 #pragma region virtual_impl
 ,,STANDARD_IUNKNOWN_METHODS(IMathFuncs)
 ,,// Returns a + b
 ,,STDMETHODIMP Add(double a, double b, double& R);
 ,,STDMETHODIMP Sub(double a, double b, double& R);
 #pragma endregion
 ,};
 
 ,STDMETHODIMP MathFuncs::Add(double a, double b, double& R) { R=a+b; return 0; }
 ,STDMETHODIMP MathFuncs::Sub(double a, double b, double& R) { R=a-b; return 0; }
 
 EXPORTC
 const IMathFuncs* Math_CreateObject() { return new MathFuncs; }
 
 }
Macro Macro2345 interface# IMathFuncs :IUnknown,double'Add(double'a double'b)
 ,double'Sub(double'a double'b)
 ,{1DD0DD58-59C7-4308-93B8-40EEDEDE2415}
 
 dll- "my.dll" IMathFuncs'Math_CreateObject
 
 IMathFuncs m=Math_CreateObject
 out m.Add(5.7 2)
 out m.Sub(5.7 2)
 
	
	
	
		
	Posts: 133Threads: 15
 Joined: Jun 2014
 
	
	
		Thanks a lot for your samples and explanations.I found that the extern "C" is simpler to use than the COM interface method.
 The COM interface is "way beyond" my knowledge :-)
 But it's interesting to see that it could be done by using it.
 
 So far I've succeeded with the extern "C" method but with the COM interface I still have errors for the keywords:
 "IUnknown" = error not a class or struct name
 "STDMETHODIMP" = error identifier STDMETHODIMP is undefined
 
 1/ Do I miss any header file for "STDMETHODIMP"?
 
 2/ What tool do you use to get this ID?:
 #define IID_IMathFuncs __uuidof(IMathFuncs)
 __interface __declspec(uuid("1DD0DD58-59C7-4308-93B8-40EEDEDE2415")) //replace this with your generated GUID
 
	
	
	
		
	Posts: 12,239Threads: 144
 Joined: Dec 2002
 
	
	
		1. I don't know what exactly header need to include. In my project is #include <windows.h> and many others.2. In Visual Studio menu Tools -> Create GUID. Or in QM: _s.Guid; out _s
 
	
	
	
		
	Posts: 133Threads: 15
 Joined: Jun 2014
 
	
	
		After I add "windows.h" to my header file, I could compile your COM interface sample.And run the macro 2345 to test it, it works perfectly!
 Thank you very much for your wonderful support!
 Cheers!
 |