Firstly please let me explain what I am trying to do:
I am using Qt to build an app mainly based on webkit. This app fetches content from internet and present it to user by traditional web way.
My app has to communicate many serial port devices, such as printer, IC card reader.
These serial port devices have different models, so that they have different communication protocol.
I want separate my app with the serial port devices communcating part, so that I can only update the communcation part without updating all the app.
Do I need to write a Qt plugin/webkit plugin, or some other way to do this? Any suggestions are welcome!
Thanks
AFAIK Qt already provides a plugin mechanism.
Check the QLibrary class out and the examples there.
For the serial port part qextserialport
Build your communication part in a dll/dynamic library by using TARGET = lib and CONFIG += dll in another qmake file.
I would suggest one of the PluginManager style plugin methods with C++.
I'm writing this from 2+ year old memory so it's meant only as a loose guide, not a definitive answer.
I have included a link to a site I used to get started on a project like you describe a few years ago. It worked well with the 40+ plugins we had available.
A search for [DLL plugin C++ class] should find several of the sites for you if you don't like the one I linked.
You will have to correct for your environment/compiler/OS etc.
In essence, assume you want the ability to Open, Read, Write and Close the serial ports in your plugins.
Create a pure virtual base class (Acts as something declared as an interface in Java):
/* This is the basic plugin header file that every plugin DLL has to include
Use your compilers pragmas/keywords to export the entire class from the DLL
In Microsoft land the keywords are _declspec( dllexport ) to export the class
from the base DLL and __declspec( dllimport ) to import the class into other
code. I'm using the MS keywords here because I don't remember how this is done
in other compilers. :)
*/
#if BUILDING_BASE_PLUGIN
/* You're compiling the DLL that exports the Plugin Base
#define BASE_DLL_EXPORT declspec( dllexport )
#else
/* You're compiling code that uses the plugin base
#define BASE_DLL_EXPORT declspec( dllimport )
#endif
class DLL_EXPORT SerialPortPluginBase
{
public:
enum SerialPortPluginError{ SUCCESS = 0, ERROR_1, ERROR_2, ERROR_ETC };
virtual SerialPortPluginError Open( /*Parameters*/ ) = 0;
virtual SerialPortPluginError Read( /*Parameters*/ ) = 0;
virtual SerialPortPluginError Write( /*Parameters*/ ) = 0;
virtual SerialPortPluginError Close( /*Parameters*/ ) = 0;
static std::string pluginName = "SerialPortPluginBase";
static int version;
};
In each plugin, implement the interface based on the above class as well as a method to register/unregister the DLL with a plugin manager (see the link below).
Each plugin should go in a separate DLL/SO.
See this site for a complete example.
Hope this helps. :)
What you want is to create a Qt Plugin for your application:
http://doc.qt.io/archives/qt-4.7/plugins-howto.html
You'll be able to extend your main application through a plugin. The only thing you'll need to add to your application is the process of load plugins and add some events to call plugins methods.
Related
I am getting started with Unreal Engine 4. I come from Libgdx and I am familiarized using WebSockets clients in my games and NodeJS with 'ws' on the server.
How ever, I can't find information about Websockets and Unreal Engine 4.
I know that given that it is programmed with C++ you can add external static libraries to the unreal project.
Can I use this c++ websocket library?
https://github.com/zaphoyd/websocketpp
Will it run on Windows, Mac and console?
I am not an expert of c++ and static libraries.
Please help, thanks!
You can follow this tutorial on TCP Sockets.
You will need to make some changes on the code, as it doesn't run on UE 4.10 (the tutorial is originally from 2014).
On the .h file define 2 timer handles:
FTimerHandle TimerHandle_Connection;
FTimerHandle TimerHandle_Socket;
On the .cpp file, inside StartTCPReceiver(...) change the line where the timer is set to:
GetWorldTimerManager().SetTimer(TimerHandle_Connection, this, &AYourClass::TCPConnectionListener, 0.01, true);
and on TCPConnectionListener(...) change the line where the timer is set to:
GetWorldTimerManager().ClearTimer(TimerHandle_Connection);//optional, only if you want to stop listening for new connections
GetWorldTimerManager().SetTimer(TimerHandle_Socket, this, &AYourClass::TCPSocketListener, 0.01, true);
(Another option would be to thread these functions instead of having them in timers)
Just in case, if you are new to UE, don't add the code directly on the IDE. Go to the Content Browser > Add New > New C++ Class. You can create a new class that inherits from Actor, and when you want to start to listen to connections, you spawn that Actor.
You can use any websocket or third party asset with unreal engine. You can simply add the headers in your Build.cs file using PrivateIncludePathModuleNames for example (there's also a public include path) and it takes an array of strings where each string is a folder essentially. If you want to add a library (lib) file you can just add it like this:
if (Target.Platform == UnrealTargetPlatform.Win32 ||
Target.Platform == UnrealTargetPlatform.Win64)
{
PublicSystemLibraries.Add("crypt32.lib");
}
You can also add full paths here. If you want to do a delayed load you can just use PublicDelayLoadedDlls.Add("name") <- I may have the syntax wrong on this one but it's easy to google it.
I am currently developing on a Chromium Embedded framework app.
The project consists of a client and a helper. I need to know the bundle path from the helper, easy just use the methods of foundation.... Well I can't since I can't use foundation in the helper.
The client is a C++ based core wrapped in a objective-c++ cocoa app.
The helper is pure C++.
The two apps share an custom class for process-type-based behaviour ( see code below). The "OnBeforeCommandLineProcessing" method needs to use the bundle path! (Just changing file ending to .mm and importing foundation/cocoa does not work, as soon as i import foundation things turn ugly with a huge amount of errors). How can I get bundle path from C++ without foundation? This does not work: mainBundle = CFBundleGetMainBundle();
namespace client {
// Base class for customizing process-type-based behavior.
class ClientApp : public CefApp {
public:
ClientApp();
enum ProcessType {
BrowserProcess,
RendererProcess,
ZygoteProcess,
OtherProcess,
};
// Determine the process type based on command-line arguments.
static ProcessType GetProcessType(CefRefPtr<CefCommandLine> command_line);
protected:
// Schemes that will be registered with the global cookie manager.
std::vector<CefString> cookieable_schemes_;
private:
// Registers custom schemes. Implemented by cefclient in
// client_app_delegates_common.cc
static void RegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar,
std::vector<CefString>& cookiable_schemes);
void OnBeforeCommandLineProcessing(const CefString& process_type,
CefRefPtr<CefCommandLine> command_line) OVERRIDE;
// CefApp methods.
void OnRegisterCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(ClientApp);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_H_
Trying to import cocoa/foundation after renaming to .mm:
You're importing Foundation.h when you mean #include <CoreFoundation/CoreFoundation.h>. Foundation is an ObjC API (which is not compatible with C++). Core Foundation is a C API. When you include CoreFoundation, CFBundleGetMainBundle() should be fine. Note the CF at the start that is indicating it's part of Core Foundation, vs NS which indicates Foundation (or AppKit).
There is no need to rename this .mm. As long as you use CoreFoundation, it's fine to be a pure C++ file. Just remember that Core Foundation has its own memory management. There is no ARC. You need to remember to CFRelease anything you obtained using a function with Create or Copy in its name (or that you called CFRetain on. Full details are in the Memory Management Programming Guide for Core Foundation.
I have a C++ COM dll and I have register it with regsvr32. I want tho use the functions and class of the dll Inside my code. Unfortunatly I dont possess any .h and it doesnt come with a .tlb file. I have the documentation how to use the functions and class but there is no information about how to link the dll to my project so I could use it. I am new with using external COM interface so i'm not quite sur where I could find this information.
I have tried #import "example.dll" (dll inserted in the project folder but it looks like it doesn't work I have an unable to load dll error. My program is mixed CLR / unmanaged C++.
Any suggestions?
Thanks in advance
If enough information is provided, you can define the interfaces in a header file yourself. I would recommend using #import to import an existing COM type library and investigate the generated .tlh file for ideas. For a simple interface with functions, for example, the code looks something like this:
struct __declspec(uuid("Interface-Guid-with-Dashes")) IInterfaceName : IUnknown
{
virtual HRESULT __stdcall get_Value (/*[out,retval]*/ long * result) = 0;
virtual HRESULT __stdcall Execute (/*[in]*/ int value) = 0;
};
I have a C++ dll which is a plug-in to ADOBE Acrobat. It needs to talk often ( to and fro) and with a fair amount of complicated data-structures to a WPF process.
Any thoughts of what might be the best way to go . Need something that is a little long term and maintainable, in other words would love some ideas around something that lets both process make what looks like methods calls and some infrastructure piece does the marshaling and dispatch . I've tried Windows messages but ran into some conflict issues on ADOBE, also not really interested in anything that causes the dll to get adobe to load the CLR. Only other things that come to my mind are named pipes or http.
Thanks in Advance
Named pipes could do but you won't get a feeling of just calling functions. Named pipe are quite low-level IPC. Other IPC options are:
Windows RPC, you definitely get a feeling of just calling functions.
What about hosting a COM object in WPF application and calling it from the Adobe plugin?
I would go with COM:
Implement an interface in WPF app
generate a typelib (e.g by using regasm)
import the typelib into C++ dll
communicate
if you need bidirectional communication, C++ dll can also implement a COM interface which is then accessed from WPF application.
This is what I have used to connect legacy C++ app with new .NET service, and it works great. The biggest issue is to find people who know COM, but fortunately this doesn't require a deep understanding of COM.
your hint with COM is very intersting. I tried to implement this concept.
I have created an interface in my WPF CallDllFromWpf3Interface project:
using System.Runtime.InteropServices;
namespace CallDllFromWpf3Interface
{
[Guid("F6E0E2E8-CCC6-487B-8BF1-261265061E6A")]
public interface SetValueInterface
{
void SetValue(int value);
}
}
Then I have generated the typelib with the regasm tool:
regasm CallDllFromWpf3Interface.exe /tlb
With the "oleview" tool I can see the typelib and the interface.
The next step was to create a c++ dll project called "CallSetValueInterface".
In my CallSetValueInterface.cpp file I wrote this lines:
#import "D:\Thomas\Programming\WPF\Basics\CallDllFromWpf\CallDllFromWpf3Interface\CallDllFromWpf3Interface\bin\Debug\CallDllFromWpf3Interface.tlb"
void
CallSetValueInterface::startAcq(void)
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CallDllFromWpf3Interface::SetValueInterfacePtr Svip("f6e0e2e8-ccc6-487b-8bf1-261265061e6a");
Svip->SetValue(55);
Svip = NULL;
CoUninitialize();
}
After a successful build of the dll project I copied "CallSetValueInterface.dll" to the "CallDllFromWpf3Interface" project.
Finally I changed my WPF code to:
#region SetValueInterface Members
public void SetValue(int value)
{
MyValue = value;
}
#endregion
[DllImport("CallSetValueInterface.dll", EntryPoint = "startAcq", ExactSpelling = true, SetLastError = true)]
public static extern void StartAcqFromDll();
private void Button_Click(object sender, RoutedEventArgs e)
{
StartAcqFromDll();
}
And when the debugger came to StartAcqFromDll() there occurred an error dialog "An unhandled exception of type 'System.Runtime.InteropServices.SEHException' occurred in CallDllFromWpf3Interface.exe".
Does anybody know whats going wrong?
Regards,
ThomasL.
I am currently writing an application that will serve a similar purpose for multiple clients, but requires adaptations to how it will handle the data it is feed. In essence it will serve the same purpose, but hand out data totally differently.
So I decided to prodeed like this:
-Make common engine library that will hold the common functionalities of all ways and present the default interface ensuring that the different engines will respond the same way.
-Write a specific engine for each way of functioning....each one compiles into its own .dll.
So my project will end up with a bunch of libraries with some looking like this:
project_engine_base.dll
project_engine_way1.dll
project_engine_way2.dll
Now in the configuration file that we use for the user preferences there will an engine section so that we may decide which engine to use:
[ENGINE]
Way1
So somewhere in the code we will want to do:
If (this->M_ENGINE == "Way1")
//load dll for way1
Else If (this->M_ENGINE == "Way2")
//load dll for way2
Else
//no engines selected...tell user to modify settings and restart application
The question is...How will I import my dll(s) this way? Is it even possible? If not can I get some suggestions on how to achieve a similar way of functioning?
I am aware I could just import all of the dlls right at the start and just choose which engine to use, but the idea was that I didn't want to import too many engines for nothing and waste resources and we didn't want to have to ship all of those dlls to our customers. One customer will use one engine another will use a different one. Some of our customer will use more than one possibly hence the reason why I wanted to externalize this and allow our users to use a configuration file for engine switching.
Any ideas?
EDIT:
Just realized that even though each of my engine would present the same interface if they are loaded dynamically at runtime and not all referenced in the project, my project would not compile. So I don't have a choice but to include them all in my project don't I?
That also means they all have to be shipped to my customers. The settings in the configuration would only dictate with class I would use to initialize my engine member.
OR
I could have each of these engines be compiled to the same name. Only import one dll in my main project and that particular engine would be used all the time. That would render my customers unable to use our application for multiple clients of their own. Unless they were willing to manually switch dlls. Yuck
Any suggestions?
EDIT #2:
At this point seeing my options, I could also juste make one big dll containing the base engine as well as all the child ones and my configuration to let the user chose. Instead of referencing multiple dlls and shipping them all. Just have one huge one and ship/reference that one only. I am not too fond of this either as it means shipping one big dll to all of my customers instead of just one or two small ones that suit there needs. This is still the best solution that I've come up with though.
I am still looking for better suggestions or answers to my original question.
Thanks.
Use separate DLLs for each engine and use LoadLibrary in your main project to load the specific engine based on the configuration.
Have your engine interface in some common header file that all engines will derive from and this interface will be used in your main project aswell.
It might look like this:
// this should be an abstract class
class engine {
public:
virtual void func1() = 0;
virtual void func2() = 0;
...
};
In each different engine implementation export a function from the DLL, something like this:
// might aswell use auto_ptr here
engine* getEngine() { return new EngineImplementationNumberOne(); }
Now in your main project simply load the DLL you're interested in using LoadLibrary and then GetProcAddress the getEngine function.
string dllname;
if (this->M_ENGINE == "Way1")
dllname = "dllname1.dll";
else if (this->M_ENGINE == "Way2")
dllname = "dllname2.dll";
else
throw configuration_error();
HMODULE h = LoadLibraryA(dllname.c_str());
typedef engine* (*TCreateEngine)();
TCreateEngine func = (TCreateEngine)GetProcAddress(h, "getEngine");
engine* e = func();
The name of the exported function will probably get mangled, so you could either use DEF files or extern "C" in your DLLs, also don't forget to check for errors.
The solution I came to is the following:
Engine_Base^ engine_for_app;
Assembly^ SampleAssembly;
Type^ engineType;
if (this->M_ENGINE == "A")
{
SampleAssembly = Assembly::LoadFrom("path\\Engine_A.dll");
engineType = SampleAssembly->GetType("Engine_A");
engine_for_app = static_cast<Engine_Base^>(Activator::CreateInstance(engineType, param1, param2));
}
else
{
SampleAssembly = Assembly::LoadFrom("path\\Engine_B.dll");
engineType = SampleAssembly->GetType("Engine_B");
engine_for_app = static_cast<Engine_Base^>(Activator::CreateInstance(engineType, param1, param2, param3, param4));
}
I used the answer from Daniel and the comments that were made on his answer. After some extra research I came across the LoadFrom method.