Use C++ managed Form from unmanaged C++ project - c++

please I need your help, I googled a lot and any answer for this problem....
I have a solution that includes various Unmanaged C++ projects, but now I need to use a Visual C++ Form (that is Managed) into the main unmanaged project, and comunicate with it.
It's possible to do it? via wrapper, dll.... how?
I googled a lot but all the cases I found talk about how use Unmanaged into Managed, or are incomplete examples. I found this example and seems that it works, but doesn't compile.
http://www.codeproject.com/Articles/9903/Calling-Managed-Code-from-Unmanaged-Code-and-vice
I'm using Visual Studio 2012.
Thanks a lot.

Finally I found a solution...
1 - When I want to have the FORM control into non managed code (for create, show, hide, set controls value...) I exported static methods as __declspec(dllexport)
2 - When I want to send info from FORM to non managed code I do it using callbacks.
I'm going to explain it....
Firstly... I create a CLR project as DLL, create a windows Form (MyForm.h) with some controls:
1 exit button
1 button that SEND info TO NON MANAGED code
and 1 checkbox that RECEIVE new status FROM NON MANAGED code
(I ommit the gode generated by visual studio)
namespace TestUnmanaged {
... code ommitted ...
private: System::Void QuitBtn_Click(System::Object^ sender, System::EventArgs^ e) {
this->Close();
}
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
//Call to non managed function!!!!
CallToCallBack();
}
};
}
Then, I create a static (non managed) class that has a pointer to the form, and manage it's creation, etc..
//Type of my specific callback function
typedef std::function<bool (int& _msg)> T_CALLBACK_FUNC;
public class unmanagedClass
{
public:
unmanagedClass();
~unmanagedClass();
void CreateForm( void );
HWND getFormHandle(void) const;
void setCallbackFunction(T_CALLBACK_FUNC _callbackFuntion);
void callToCallbackFunction(int _value);
//public for fast tests
gcroot<TestUnmanaged::MyForm^> p;
private:
HWND m_hWnd;
T_CALLBACK_FUNC m_funcionCallback;
};
unmanagedClass s_unmanaged;
Here's the .cpp implementation...
//////////////////////////////////////////////////////////////////////////
// Static Functions for DLL_EXPORT
//////////////////////////////////////////////////////////////////////////
void CloseForm( void )
{
Application::Exit();
}
void CallToCallBack( void )
{
int valor = 5;
s_unmanaged.callToCallbackFunction(valor);
}
//////////////////////////////////////////////////////////////////////////
// Methods for Unmanaged Class
//////////////////////////////////////////////////////////////////////////
HWND unmanagedClass::getFormHandle( void ) const
{
return m_hWnd;
}
unmanagedClass::unmanagedClass()
{
p = gcnew(TestUnmanaged::MyForm);
}
unmanagedClass::~unmanagedClass()
{
delete (p);
}
void unmanagedClass::CreateForm( void )
{
Application::Run(p);
}
void unmanagedClass::setCallbackFunction( T_CALLBACK_FUNC _callbackFuntion )
{
m_funcionCallback = _callbackFuntion;
}
void unmanagedClass::callToCallbackFunction( int _value )
{
m_funcionCallback(_value);
}
Now, I create all the static functions that will be exported as dllexport:
__declspec(dllexport) void CreateFormDLL(void)
{
s_unmanaged.CreateForm();
}
__declspec(dllexport) void CloseFormDLL(void)
{
s_unmanaged.p->Close();
}
__declspec(dllexport) void ShowFormDLL(void)
{
s_unmanaged.p->Show();
}
__declspec(dllexport) void HideFormDLL(void)
{
s_unmanaged.p->Hide();
}
__declspec (dllexport) void setCallbackFunctionDLL( T_CALLBACK_FUNC& _doFunction)
{
s_unmanaged.setCallbackFunction(_doFunction);
}
__declspec (dllexport) void setCheckBoxDLL( bool _newValue )
{
s_unmanaged.p->getCam01ChkBox()->Checked = _newValue;
}
__declspec (dllexport) HWND getFormHandleDLL( void )
{
return (HWND)s_unmanaged.p->Handle.ToPointer();
}
Now.... I create the Win32 console App project and link the Managed project. This will be the main process, and the class "ManagedWrapper". Here is the source....
class ManagedWrapper
{
public:
ManagedWrapper(void);
~ManagedWrapper(void);
void init(void);
void createForm(void);
void showForm(void);
void closeForm(void);
void setCam01ChkBox(const bool _newValue);
private:
void createFormThread(void);
static bool callBackReceiver(int a);
};
#include "ManagedWrapper.h"
#include <thread>
__declspec(dllimport) void CreateFormDLL(void);
__declspec(dllimport) void CloseFormDLL(void);
__declspec(dllimport) void ShowFormDLL(void);
__declspec(dllimport) void HideFormDLL(void);
typedef std::function<bool (int& _msg)> T_CALLBACK_FUNC;
__declspec (dllimport) void setCallbackFunctionDLL( T_CALLBACK_FUNC& _doFunction);
__declspec (dllimport) void setCheckBoxDLL( bool _newValue );
ManagedWrapper::ManagedWrapper(void)
{
}
ManagedWrapper::~ManagedWrapper(void)
{
}
void ManagedWrapper::createForm( void )
{
std::thread showThread (&ManagedWrapper::createFormThread, this);
showThread.detach();
}
void ManagedWrapper::createFormThread( void )
{
CreateFormDLL();
}
void ManagedWrapper::closeForm( void )
{
CloseFormDLL();
}
void ManagedWrapper::showForm( void )
{
ShowFormDLL();
}
void ManagedWrapper::init( void )
{
setCallbackFunctionDLL(T_CALLBACK_FUNC(&ManagedWrapper::callBackReceiver));
}
bool ManagedWrapper::callBackReceiver( int a )
{
printf("Hello world. Parameter value = %d\n",a);
return true;
}
void ManagedWrapper::setCam01ChkBox( const bool _newValue )
{
setCheckBoxDLL( _newValue );
}
And finally.... the simplest use from the main(), create the Form, set the checkbox values, if the user click on the button the callback function writes on console... and finally close.
int _tmain(int argc, _TCHAR* argv[])
{
ManagedWrapper umWrap;
umWrap.init();
umWrap.createForm();
system("PAUSE");
umWrap.setCam01ChkBox(true);
system("PAUSE");
umWrap.setCam01ChkBox(false);
system("PAUSE");
umWrap.closeForm();
return 0;
}
Sorry for the long answer, but I believe that may be usefull for somebody.

Related

How to use Kotlin Multiplatform shared library interface from C++

I have a multiplatform kotlin project generating a shared library for mingwx64. Once I have generated the DLL, I have incorporated it into a C++ project and now i need to call a function that takes the implementation of an interface as a parameter, but I have no idea how to get it.
I attach example code to explain it:
//Kotlin Multiplatform code
interface InitializationEvents {
fun onComplete()
fun onError(error: String)
}
class MyClass {
fun initialize(succeed: Boolean, listener: InitializationEvents) {
if(succeed)
listener.onComplete()
else
listener.onError("Error description")
}
}
It generates a header file like this:
//libnative.h
typedef {
...
/* User functions. */
struct {
struct {
struct {
libnative_KType* (*_type)(void);
void (*onComplete)(libnative_kref_InitializationEvents thiz);
void (*onError)(libnative_kref_InitializationEvents thiz, const char* error);
} InitializationEvents;
struct {
libnative_KType* (*_type)(void);
libnative_kref_MyClass (*MyClass)();
void (*initialize)(libnative_kref_MyClass thiz, libnative_KBoolean succeed, libnative_kref_InitializationEvents listener);
} MyClass;
} root;
} kotlin;
} libnative_ExportedSymbols;
extern libnative_ExportedSymbols* libnative_symbols(void);
And now I'm using this Cpp code:
// Demo.cpp
int main()
{
libnative_ExportedSymbols* lib = libnative_symbols();
libnative_kref_MyClass myClass = lib->kotlin.root.MyClass.MyClass();
//I guess I have to do something here... 😅
libnative_kref_InitializationEvents listener = { .pinned = NULL };
lib->kotlin.root.MyClass.initialize(myClass, true, listener);
}
void myOnComplete() { }
void myOnError(const char* error) { }
It would need to be able to receive the call to the myOnComplete and myOnError functions as desired by the library.
Thank you very much.

c++ CLI Export void return __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention

I'm trying to export some void/functions from a C++ Cli that wraps C# .Net Functions.
In this moment I can properly export methods that return integer value, but when I try to export a Void, I get the error:
Error C3395 'Test2': __declspec(dllexport) cannot be applied to a function with the __clrcall calling convention ClassLibrary1
This is the full code:
#pragma once
using namespace System;
using namespace System::Reflection;
using namespace RobinHoodLibrary;
namespace ClassLibrary1 {
public ref class Class1
{
// TODO: Add your methods for this class here.
RobinHood^ robin = gcnew RobinHood();
public: int Add(int Number1, int Number2)
{
return robin->Add(Number1, Number2);
}
public: System::Void Test()
{
robin->Test();
}
public: int Test1(int i)
{
return robin->Test1(i);
}
public: System::Void Test2(String^ txt)
{
robin->Test2(txt);
}
};
}
extern __declspec(dllexport) int Add(int Number1, int Number2) {
ClassLibrary1::Class1 c;
return c.Add(Number1, Number2);
}
extern __declspec(dllexport) void Test() {
ClassLibrary1::Class1 c;
c.Test();
return;
}
extern __declspec(dllexport) int Test1(int i) {
ClassLibrary1::Class1 c;
return c.Test1(i);
}
extern __declspec(dllexport) System::Void Test2(String^ txt) {
ClassLibrary1::Class1 c;
c.Test2(txt);
}
I can easy export Add, Test and Test1 method but not Test2.
How can I to fix it ?
Thanks to support
AFAIK
You can't export methods which have C++/CLI types in arguments or in return value.
So you have to use const wchar_t* or std::wstring as parameter instead of String^.
try with gcroot<> in function Test2 like this:
System::Void Test2(gcroot<String^> txt);

c++ [gamestate] function does not take in correct argument error

Hello i have problem of compile my code
i follow http://gamedevgeek.com/tutorials/managing-game-states-in-c/ tutorial
but it fail to compile and i don't know why.
the error msg from visual studio
here is my code
the CGameEngine modify code
#include <vector>
#include "GameState.h"
#include "GameEngine.h"
class GameState;
class GameStateManager
{
public:
GameStateManager(GameEngine* engine, MSG * msg);
~GameStateManager();
void Cleanup();
void ChangeState(GameState* state);
void Update();
bool Running() { return m_running; }
void Quit();
private:
std::vector<GameState *> states;
bool m_running;
GameEngine * m_engine;
MSG *m_msg;
};
#include "GameStateManager.h"
GameStateManager::GameStateManager(GameEngine* engine, MSG * msg)
:m_engine{ engine }, m_msg{ msg }, m_running{ true }
{
}
GameStateManager::~GameStateManager()
{
}
void GameStateManager::Cleanup()
{
while (!states.empty()) {
states.back()->Exit();
states.pop_back();
}
}
void GameStateManager::Quit()
{
m_running = false;
m_msg->message = WM_QUIT;
}
void GameStateManager::ChangeState(GameState* state)
{
if (!states.empty()) {
states.back()->Exit();
states.pop_back();
}
states.push_back(state);
states.back()->Enter(m_engine, m_msg);
}
void GameStateManager::Update()
{
states.back()->Update(this);
}
the CGameState modify code
#include "GameStateManager.h"
class GameState
{
public:
GameState() {}
virtual ~GameState() {}
virtual void Enter(GameEngine * , MSG * ) = 0;
virtual void Update(GameStateManager* game) =0;
virtual void Exit() = 0;
};
one of the state class
#include "MainMenu.h"
class Logo :public GameState
{
public:
Logo();
~Logo();
static Logo* Instance()
{
return &m_Logo;
}
void Enter(GameEngine * engine, MSG * msg);
void Update(GameStateManager* game);
void Exit();
private:
static Logo m_Logo;
};
#include "Logo.h"
Logo::Logo()
{
}
Logo::~Logo()
{
}
void Logo::Enter(GameEngine * engine, MSG * msg)
{
m_GameEngine_Info = engine;
m_msg = msg;
}
void Logo::Update(GameStateManager* game)
{
}
void Logo::Exit()
{
}
i get no compile error when editing the code, but when i try compile it get this error.
You have circular includes. Use include guards and replace
#include "GameStateManager.h"
with
class GameStateManager;
in GameState.h. Move this include into GameState.cpp.
Do similar with #include "GameEngine.h" and #include "GameState.h" in GameStateManager.h and GameStateManager.cpp.

C++ help writing a class with declaration on header file

Well, hi there.
I'm new to c++ and I'm having some issues that I'm not sure what is causing them.
This is my main:
#include "GameWindow.h"
int main(void)
{
GameWindow * game_window = new GameWindow(true);
/* loop the game */
while (game_window->GetRunning())
{
// update
game_window->Update();
// draw
game_window->Draw();
}
delete game_window;
return 0;
}
and this is my header:
class GameWindow
{
private:
bool _running;
//GLFWwindow* _window;
public:
void SetRunning(bool new_val);
bool GetRunning();
GameWindow(bool running);
void Draw();
void Update();
}
and my c++ file:
#include "GameWindow.h"
void GameWindow::SetRunning(bool new_val)
{
_running = new_val;
}
bool GameWindow::GetRunning()
{
return _running;
}
GameWindow::GameWindow(bool running) :
_running(running)
{
}
void GameWindow::Draw()
{
}
void GameWindow::Update()
{
}
While going through all of this I find it tough to find why Visual Studio refuse to compile this code.
It's raising errors about how 'SetRunning' is overloading a function which differs only in return values, and that the return type of main should be Int and not GameWindow, and with all of this I just went completely lost.
Tried to put 'SetRunning' as a comment to simplify the issue but instead it raised the same on 'GetRunning' instead.
I'm guessing it's a really stupid mistake that is easy to fix, but still, can't find it.
Thank you for your time, and I'll appreciate any kind of help.
Missing ; at the end of class definition.
class GameWindow
{
// .....
}; // Missing semi-colon
Missing ; in class defination
{
};
because of this when you include the file in program then compiler not found the end of the class hence it says return type of main should be int not GameWindow

Export observer pattern from a c++ library in c code

I have a c++ shared library that can generate some event. I've an interface for the listener and a class that is able to register observers and fire events.
This library may be used used from java, C# and C++ code( compiled with differenc compilers) so I've two file headers: *.h for ANSI C interface and *.hpp for use library directly from C++ code. Now I cannot figure how export observer pattern with a C-like interface.
Here is a little snippet of how code is structured.
// hpp file
class IListener
{
public:
virtual ~IListener() {}
virtual void event1( int ) = 0;
virtual void event2() = 0;
};
using IListenerPtr = std::shared_ptr< IListener >;
class Controller
{
public:
Controller( IListenerPtr listener );
void addListener( IListenerPtr listener );
private:
void threadFunc()
{
while ( true )
{
// an event occured
for ( auto& e : mListeners )
e->event1( 2 );
for ( auto& e : mListeners )
e->event2();
}
}
private:
std::vector< IListenerPtr > mListeners;
};
// h file
#if defined( __MSCVER ) || defined( __MINGW32__ ) || defined( __MINGW64__ )
# define LIB_CALLBACK __stdcall
# define LIB_CALL __cdecl
# if defined( AAMS_EXPORTS )
# define LIB_API __declspec( dllexport )
# else
# define LIB_API __declspec( dllimport )
# endif
#else
# define LIB_API
#endif // WIN32
typedef int libError;
LIB_API libError LIB_CALL libInit( ???? );
How can I make this library usable from C code? A first attempt maybe:
typedef struct libListenerTag
{
typedef void (LIB_CALLBACK *Event1Func)( int );
typedef void (LIB_CALLBACK *Event2Func)();
Event1Func Event1;
Event2Func Event2;
} libListener;
LIB_API libError LIB_CALL libInit( libListener* listener );
and in someway bind libListener to IListener
// cpp file
class CListener : public IListener
{
public:
CListener( libListener* listener
: mListener( listener )
{
}
void event1( int i ) { mListener->Event1( i ); }
void event2() { mListener->Event12(); }
private:
libListener* mListener;
}
Controller* g_controller = nullptr;
LIB_API libError LIB_CALL libInit( libListener* listener )
{
g_controller = new Controller( make_shared< CListener >( listener );
// ...
}
This method doesn't look very good for me. Is a better way to accomplish this?
You're missing something that's standard in C event callbacks: a context pointer.
In C++ your IListener subclass gets an implicit this pointer in its callbacks, meaning it can store state and context info in the instance.
For free functions, you don't have this, so you need to add an explicit argument.
/* c_interface.h */
typedef void (*EventCallback1)(void *context, int arg);
typedef void (*EventCallback2)(void *context);
struct Listener; /* opaque type */
struct Listener *create_listener(EventCallback1, EventCallback2, void *context);
void destroy_listener(struct Listener*);
so from the C side, you pack whatever state you need into a structure, pass it into create_listener as your context, and get it passed back to your functions when they're called.
// c_implementation.cpp
extern "C" {
#include "c_interface.h"
struct Listener: public IListener {
EventCallback1 cb1;
EventCallback2 cb2;
void *context;
Listener(EventCallback1 e1, EventCallback2 e2, void *c)
: cb1(e1), cb2(e2), context(c)
{}
virtual void event1(int arg) {
(*cb1)(context, arg);
}
virtual void event2() {
(*cb2)(context);
}
};
Listener *create_listener(EventCallback1 cb1, EventCallback2 cb2, void *context) {
return new Listener(cb1, cb2, context);
}
}
The client code looks something like
#include "c_interface.h"
struct MyContext {
int things;
double needed;
int to_handle;
char callbacks[42];
};
void cb0(void *context) {}
void cb1(void *context, int arg) {
struct MyContext *c = (struct MyContext *)context;
c->things = arg;
}
void foo() {
struct MyContext *context = malloc(sizeof(*context));
struct Listener *l = create_listener(cb1, cb0, context);
...