PDA

View Full Version : Create dll/idl to use with visual studio 2010



Sajjmon
30th July 2012, 10:06
I've created an application using Qt Creator and now I would like to use the functionalities within an C# visual studio solution. With this i want to create a library from my QT application and add this as a reference within my visual studio solution. I've realized a few things when searching the web for a solution.

I would like to know what is the best way of doing this, I've tried creating a library file with the use of TEMPLATE = lib in my .pro file but as I relaize I then have to use the .h file and this is now possible as I in my visual studio use C# as language but my QT project is developed with c++.

I need to create a COM interop dll as I understand it but all I can find online is either eight years old or done through visual studio itself.

So what I want to do is to create a simple library file which I can use without the .h file, which I can add to my visual studio solution, without any GUI necessary. I'm only going to use the functions within the dll as help functions to my visual studio solution.

If someone please can help me with a small tutorial or step by step guide this would really really help me?

Thanks!

high_flyer
30th July 2012, 11:39
Google for loading unmanaged C++ DLL in C# - there are many tutorials on how to do it.
This is not a Qt issue.

ChrisW67
30th July 2012, 11:44
ActiveQt can be used to create an in-process COM server which is, I assume, usable from .Net land.

Sajjmon
30th July 2012, 16:30
Thanks for your reply.
What I'm looking for is how to create an Assembly or COM component from an QT Application?

I realize that a com component need some kind of GUIID and a need to extract the functions from the application.
This is what I got right now:



#define APPTOLIB_EXPORT Q_DECL_EXPORT
using namespace std;
class APPTOLIB_EXPORT MyMathFuncs : public QObject
{
Q_OBJECT

Q_CLASSINFO("ClassID", "{b50a71db-c4a7-4551-8d14-49983566afee}")
Q_CLASSINFO("InterfaceID", "{4a427759-16ef-4ed8-be79-59ffe5789042}")
Q_CLASSINFO("RegisterObject", "yes")

public:
MyMathFuncs(QObject* parent = 0);
// Returns a + b
static double Add(double a, double b);

// Returns a / b
// Throws DivideByZeroException if b is 0
static double Divide(double a, double b);
};

MyMathFuncs::MyMathFuncs(QObject *parent) : QObject(parent)
{
setObjectName("From QAxFactory");
}

double MyMathFuncs::Add(double a, double b)
{
return a + b;
}

double MyMathFuncs::Divide(double a, double b)
{
if (b == 0)
{
throw new invalid_argument("b cannot be zero!");
}

return a / b;
}


QAXFACTORY_BEGIN("{edd3e836-f537-4c6f-be7d-6014c155cc7a}", "{b7da3de8-83bb-4bbe-9ab7-99a05819e201}")
QAXCLASS(MyMathFuncs)
QAXFACTORY_END()

I can access the interface but I don't get up any functions. I've been able to extract seperate functions but when adding them to a class I only get an interface when adding the reference to my visual studio solution. I which to be able to create a new object of MyMathFuncs and then access the functions which I've made available.

Maybe my title wasn't so well written but what I want is to use my QT c++ class by adding a dll as reference in Visual Studio C# where I can then get hold of the functions/classes which I have made extern.?

amleto
30th July 2012, 17:51
I've created an application using Qt Creator and now I would like to use the functionalities within an C# visual studio solution. With this i want to create a library from my QT application and add this as a reference within my visual studio solution. I've realized a few things when searching the web for a solution.

I would like to know what is the best way of doing this, I've tried creating a library file with the use of TEMPLATE = lib in my .pro file but as I relaize I then have to use the .h file and this is now possible as I in my visual studio use C# as language but my QT project is developed with c++.

I need to create a COM interop dll as I understand it but all I can find online is either eight years old or done through visual studio itself.

So what I want to do is to create a simple library file which I can use without the .h file, which I can add to my visual studio solution, without any GUI necessary. I'm only going to use the functions within the dll as help functions to my visual studio solution.

If someone please can help me with a small tutorial or step by step guide this would really really help me?

Thanks!

you can use COM (yuck!), but p/invoke is simpler and easier for simple dlls with unmangled symbols (use external "C"). Search elsewhere though, this is definitely not Qt related.

tescrin
30th July 2012, 18:23
As someone who's been digging into COM for a few weeks, while it is one possible solution (as it'll be a layer between the two) it's... a lot of work.

Further, it won't necessarily be compatible if you shift it somewhere else. In order to use COM you'll have to be adding (at least one) entry to the registry and accessing it at runtime. Unless you build a proper install/batchfile/something this won't be usable by another computer without manually editing the registry (or using your batch file that does it for you manually.)

That said, COM will work, but it's the long road to success here. I imagine the tuts that high_flyer mentioned will be easier.



COM Stuff:
If you wish to do COM I'll suggest the book i've been going through: COM and ATL 3.0 by Andrew Troelson. It gives a good quick-and-dirty hands on of COM by first pretending to build COM like client/servers with C++, then moving into building actual COM objects by hand, then using ATL to actually use COM more efficiently. Most material you find on standard COM *WILL* be 8 years old or so. COM doesn't change over time! (An extremely important concept.) To expand COM they add new classes (either inheriting from old ones as a means to "update" them, or building entirely new classes.); I.E. COM+ adds a bunch of features by subclassing or adding new content. Standard COM usage hasn't and (AFAIK) won't change; so old material is gold aside from deprecated C++ headers and such. The book I mentioned happens to be at least 10 years old and I've had no issues compiling or getting the code to run just fine.

Still, seems like a very complicated way to utilize a DLL between languages for something this small. COM is more for an official release that you want:
--People to be truly abstracted from the implementation
--People to be able to use several language types in a compatible way (i.e. a company building a large project with many different programmers specialized in different languages)

A good example is a project I'm working on where I'm tearing a GUI away from it's COM layer and replacing it. By using COM I don't have to actually change anything but GUI code to update it. This is good because the language it's currently in is now unsupported so being able to recode only this portion of it leaves a usable product.

Similarly as long as you conform to the contract COM allows you to update from the other direction. You could replace the entire codebase that controls your hardware beneath the GUI implementation, without ever touching the COM layer or the GUI layer.

Sajjmon
31st July 2012, 08:11
As someone who's been digging into COM for a few weeks, while it is one possible solution (as it'll be a layer between the two) it's... a lot of work.

Further, it won't necessarily be compatible if you shift it somewhere else. In order to use COM you'll have to be adding (at least one) entry to the registry and accessing it at runtime. Unless you build a proper install/batchfile/something this won't be usable by another computer without manually editing the registry (or using your batch file that does it for you manually.)

That said, COM will work, but it's the long road to success here. I imagine the tuts that high_flyer mentioned will be easier.



COM Stuff:
If you wish to do COM I'll suggest the book i've been going through: COM and ATL 3.0 by Andrew Troelson. It gives a good quick-and-dirty hands on of COM by first pretending to build COM like client/servers with C++, then moving into building actual COM objects by hand, then using ATL to actually use COM more efficiently. Most material you find on standard COM *WILL* be 8 years old or so. COM doesn't change over time! (An extremely important concept.) To expand COM they add new classes (either inheriting from old ones as a means to "update" them, or building entirely new classes.); I.E. COM+ adds a bunch of features by subclassing or adding new content. Standard COM usage hasn't and (AFAIK) won't change; so old material is gold aside from deprecated C++ headers and such. The book I mentioned happens to be at least 10 years old and I've had no issues compiling or getting the code to run just fine.

Still, seems like a very complicated way to utilize a DLL between languages for something this small. COM is more for an official release that you want:
--People to be truly abstracted from the implementation
--People to be able to use several language types in a compatible way (i.e. a company building a large project with many different programmers specialized in different languages)

A good example is a project I'm working on where I'm tearing a GUI away from it's COM layer and replacing it. By using COM I don't have to actually change anything but GUI code to update it. This is good because the language it's currently in is now unsupported so being able to recode only this portion of it leaves a usable product.

Similarly as long as you conform to the contract COM allows you to update from the other direction. You could replace the entire codebase that controls your hardware beneath the GUI implementation, without ever touching the COM layer or the GUI layer.

Thanks for the information. The actual project which I'm going to be using is actual much larger, the small class above was just an example I'm working with so I'll get started.

I've tried to use the unmangled dll import and it seems to work, so long that I don't use any QT code. I'm gonna keep on that track I think because as you said, the COM way seems like it's alot of extra work, would be nice though. Thanks everyone!

Sajjmon
31st July 2012, 14:15
I've now been able to create a COM component out of my smalll project and can access one specified method. The problem is now that when I run my dll through an C# Console Application in Visual Studio I get this error message:
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll

Additional information: Retrieving the COM class factory for component with CLSID {FA11D634-3F6D-4DFF-8FE7-7528A0373411} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).

What I have now is:

main.cpp


#include "ItShouldWork_global.h"
#include <QObject>
#include <QAxFactory>
#include <QAxBindable>
class ITSHOULDWORKSHARED_EXPORT ItShouldWork : public QObject
{
Q_OBJECT
Q_CLASSINFO("ClassID", "{fa11d634-3f6d-4dff-8fe7-7528a0373411}")
Q_CLASSINFO("InterfaceID", "{1a41b926-eaec-4beb-9f49-4a914eebc6e1}")
Q_CLASSINFO("RegisterObject", "yes")

Q_PROPERTY(QString id READ id)

public:
ItShouldWork(QObject* parent = 0);
QString test(QString a, QString b);

QString id() const { return objectName(); }
};

ItShouldWork::ItShouldWork(QObject* parent) : QObject(parent)
{
}

QString ItShouldWork::test(QString a, QString b)
{
return a + " - " + b;
}

#include "main.moc"

QAXFACTORY_BEGIN("{f9e2e91a-ca63-4e5a-85b7-5bb65b8ee358}", "{90873f03-a81a-4007-8652-b9c134e72126}")
QAXCLASS(ItShouldWork)
QAXFACTORY_END()

and then when trying to instantiate it in my c# Console application:

Console.WriteLine("Testing: ");

itshouldworkLib.ItShouldWork it = new itshouldworkLib.ItShouldWork();

Console.WriteLine("Worked id: " + it.id);

This stops the program and shows the error message above, any ideas?

tescrin
31st July 2012, 17:43
This isn't exactly a COM forum :P, but...

were I to guess I'd say that in your driver (your main function or whatever you're actually trying to use the ClassFactory from) you're probably missing the "CoInitialize(null)" statement. I recently forgot to add that in and had my HRESULT on classfactory returning failure; hence my guess.

If not that, I'll look over it again, but I'm no expert by any means.

EDIT:
Congrats on your quick work in COM! Kind of a cool concept/programming style when you learn about it.

Sajjmon
31st July 2012, 18:30
This isn't exactly a COM forum :P, but...

were I to guess I'd say that in your driver (your main function or whatever you're actually trying to use the ClassFactory from) you're probably missing the "CoInitialize(null)" statement. I recently forgot to add that in and had my HRESULT on classfactory returning failure; hence my guess.

If not that, I'll look over it again, but I'm no expert by any means.

EDIT:
Congrats on your quick work in COM! Kind of a cool concept/programming style when you learn about it.

Yes I know and I'm sorry about that. Actually I created the COM dll using QAxFactory so its not completely out of order...:P

Thanks, but I can't say I really know everything I did. The classFactory is created through QAxFactory as I understand it and I wonder if the problems lies in how it creates the COM component. I've searched around for the error message but no solution out there seems to help me... I tried using tlbimp.exe to create an assembly from it but the same message appears again...
I'll try to see how the CoInitialize method works, maybe you can give me an example of how to implement it with a corresponding COM method?

I'm very thankful for you taking your time and helping me, the book you linked seems interesting, maybe take a look on buying that later.. Would be nice to get this working soon! :)

tescrin
31st July 2012, 18:45
Er, well so far the stuff I've done is building COM objects from scratch.

When you call ClassFactory in C++ you have to call CoInitialize(NULL) sometime before that point; it initializes the "COM Subsystem." Every thread using COM libraries has to call it before asking the COM for anything.

I'm not 100% sure, but I'm thinking you just need to start off your main thread (whichever is using QAxFactory) with the statement
CoInitialize(NULL);
//...stuff
CoUninitialize(); //be nice to the poor COM subsystem :)

Sajjmon
1st August 2012, 10:52
Thanks, I'll take a look at that.
Seems like QAxFactory does all the underlying work with COM registration/initialization and so on but I'm not completely sure, it actually just should work if you read the QT docs about ActiveQT, at least that's how i understand it.

The error I get seem to have something with security permissions issue or something, tried the solutions some people gave but nothing worked.. wondering if I should go over to C++/CLI instead...

Thanks for all your help anyway!