Create Managed Object From Unmanaged Class Function - visual-c++

I am trying to create a Managed C++/CLI object in unmanaged code.
Is this possible?
If so, am I doing it right? see code below
#include <vcclr.h>
#include <ManagedClass.h>
// compiled with /clr
namespace X
{
class UnmanagedClass
{
UnmanagedClass(){}
~UnmanagedClass(){}
gcroot<Y::ManagedClass^> m_guiControl;
void functionA()
{
m_guiControl = new gcroot<Y::ManagedClass^>;
}
}
}
// compiled into Managed dll with /clr
// in file ManagedClass.h in a separate project
using namespace System::ComponentModel;
// more usings here ..etc
namespace Y {
public ref class ManagedClass : public System::Windows::Forms::UserControl
{
// implementation here
}
}
When I compile the UnmanagedClass source file, I keep getting a whole lot of errors with the first one being error C2039: 'ComponentModel' : is not a member of 'System'. How come it is not recognising ComponentModel?
I thought this was suppose to be IJW (it just works) ;-)

Here's an example for a wrapper:
class UnmanagedClass
{
gcroot<ManagedClass^> m_managed;
public:
UnmanagedClass()
{
m_managed = gcnew ManagedClass();
}
};
Look here:
C++/CLI - Managed class to C# events
wrapper to c++/cli
Edit:
When you get an error on a using statement, and you know it's supposed to exist, It's usually because that dll isn't referenced.
Go to the projects references, choose add reference.
You can add .Net assemblies in the .Net tab. Find the one you need and add it.

Related

Using Thread in in Mixed App C++ /cli to Call native Function in native class from managed class

I am working on mixed application, using both managed & native codes
I want to call a function deployed in a native class from Main() function located in Program.cpp which is managed class.
i tried using std::thread but failed with /cli
i tried to use Managed System::Threading::Thread but failed because i need to call a native function in a native class.
So how i can handle thing without using any third-party?
If you start from a native project you need to do the following steps:
Select project properties and change the option "No Common Language Runtime Support" to "Common Language Runtime Support /clr".
Open the "Property Manager" from "View" menu / "Other Windows" and add the property sheet "C++ Common Language Runtime Support" to the needed configuration (eg.: Debug | Win32) on my system this sheet is under "C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140". I use the "Microsoft.Cpp.ManagedExtensions.props" file.
You need to remove std::thread completely.
headerish:
#pragma once
#include<stddef.h>
using namespace System;
using namespace System::Threading;
namespace FooSpace
{
// Native stuff
public class Native
{
public:
static void Foo() { }
void Bar() {
}
};
// Managed stuff
public ref class Managed
{
private:
Native* m_Native;
public:
Managed()
{
m_Native = new Native();
}
~Managed()
{
if (NULL != m_Native)
{
delete m_Native;
m_Native = NULL;
}
}
void Bar()
{
m_Native->Bar();
}
static void ThreadCall(Object^ o)
{
auto me = (Managed^)o;
me->Bar(); // Call a method of an instance of the native class
Native::Foo(); // Call a static method of the Native class
}
void StartThread()
{
auto t = gcnew Thread(gcnew ParameterizedThreadStart(ThreadCall));
t->Start(this);
t->Join();
}
};
}
soure file:
#include "stdafx.h"
#include "CppCli_Native.h"
using namespace FooSpace;
int main()
{
Native::Foo(); // call native static method
auto native = new Native(); // create native instance
native->Bar(); // call native method
auto managed = gcnew Managed();
managed->Bar(); // This will call bar
managed->StartThread(); // This will start a thread
delete managed;
Console::ReadLine();
return 0;
}
Edit: It turns out that you don't need to use IntPtr to store native class.
I find this answer also useful, it also gives us a fast introduction to c++-cli syntax.

How do I access a form's control from another thread?

Using VC++ 2010.
I want to access a form's control from a class in another thread.. and can't figure out the best (or any) way to do this. How can I pass a reference of my form instance? Im using createthread() as opposed to the managed version, wanting to make my app compatible with XP.
I've tried passing a reference and other values in a struct through the lpParameter, but I can't seem to figure out how to declare the reference properly.
ref class SZClass {
private:
FMain ^bound_form;
int server_port;
public:
void BindForm(FMain ^bf);
void Initialize(int sp)
}
struct param_data {
public:
FMain ^form_tobind;
int port_num;
}
are giving me errors:
error C2143: syntax error : missing ';' before '^'
FMain is the name of my form class, and I have a delegate method already set up to make it multithread safe:
public:
FMain(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
void FMain::PrintConsole(std::string mzg) {
String ^Smzg = marshal_as<String^>(mzg);
if (this->textBox1->InvokeRequired) {
SetTextDelegate^ d = gcnew SetTextDelegate(this, &FMain::PrintConsole);
this->Invoke(d, gcnew array<Object^> { Smzg });
} else {
textBox1->Text += Smzg;
textBox1->SelectionStart = textBox1->TextLength;
}
}
How do I declare a reference to my form?
Or is there an easier or better way to do this?
I don't know what forms library you're using, but the general rule of thumb for your question is, "Don't."
Unless you have a peculiar GUI library, Windows UI is thread-affinitized. All access to UI elements should be done via the ui's affinitized thread. Manipulating UI state from an unaffinitized execution context should be done by marshaling the update request to the affinitized context. It should not be done directly.

How to access a class in a namespace which is in different project?

I have three projects under another project of which each contains one namespace. Now among them I need to call a class which is under a namespace in visual studio 2008. Please don't ask me to add the dependencies to the main project so that I can access the namespace and all the classes in that just like local namespace which I can't do due to some restrictions. Tell me something like derived class concept so that I can access that class.
The LanguageTable class which I want to call is as follows:
#define GFX_LANGUAGE_MAX 20
namespace gfx_viewer_win32
{
public ref class LanguageTable
{
public:
static Dictionary<String ^, List<String ^>^> ^ language_string_table;
static array<String ^> ^language_string_id;
LanguageTable(void)
{
}
~LanguageTable(void)
{
}
};
}
The place from where i want to call LanguageTable class is as follows:
#pragma once
using namespace gfx_coder_prj_parser;
namespace Code_generator
{
public ref class CCodeGenerator : CCodeParserMultiLayer
{
CCodeGenerator(void)
{
}
~CCodeGenerator(void)
{
}
/*============I want to call LanguageTable class from here==========*/
};
}
If you don't want to add the assembly of LanguageTable class as a reference, you can reach it by System.Reflection. First load the assembly and create an instance of LanguageTable and now you can call methods,access properties of it by searching for by their names like
Assembly ^ langTableAssembly = Assembly::Load("assembly_name" or binary_data_of_assembly );
object ^ langTable = langTableAssembly->CreateInstance("gfx_viewer_win32::LanguageTable", ...with_other_params);
Type ^ langTableType = langTable->GetType();
MemberInfo ^ langStringID = langTableType.GetMember("language_string_id")[0];
MethodInfo ^ someMethod = langTableType.GetMethod("method_name");
someMethod->Invoke(langTable, ...other_params);
It is not a good approach though. It depends on the names, any change of the names (via refactoring etc.) you have to fix the code above. And I cannot say, this has the best performance.
Lastly, once loaded, the assembly of LanguageTable will not be unloaded during the execution of program. If you wish to unload it, this is another story called "playing with Appdomains".
Here and here are some links to begin with.

Why can't I store a managed variable in an unmanaged class?

I have user interface setup in visual studio 2005 that has a textbox and a button. I am trying to store the text in the textbox when the button is pressed using storeText(String^). My compilation error says "cannot declare a managed variable in an unmanaged class". Why can't I do this? What is the proper solution to my problem. I am using visual c++.
#include <string>
using System::String;
class Stuff
{
public:
Stuff()
{
}
void storeText(String^ s)
{
something = s;
}
String^ getText()
{
return something;
}
private:
String^ something;
};
If you're in unmanaged code, then the GC won't know what references you have or haven't got around. You're supposed to convert it to a native std::string and then use that.

Visual C++ static library

I am writing a c++ static library A.lib in visual studio 2008. In my static library, I am using few APIs exposed by another static library B.lib(.lib).
I have a written an application that uses A.lib. Since few header files in A.lib are using headers from B.lib, my application wants a path of B.lib header files. How can I avoid my application so that I need not to provide path of B.lib header files for compilation ?
Refrain from using types from B-headers in the interface of your library. A good way of totally hiding the implementation is using the factory-pattern along with pure abstract base classes as interfaces. You will still have to link B.lib in your application though.
Sample Before:
// A.h
#include "B.h"
class Foo {
public:
void DoStuff();
private:
B::Bar Data; // B::Data comes from library B
};
This in your header adds a dependency to B.
With Factory, your application now uses IFoo.h instead of A.h:
// IFoo.h
class IFoo {
public:
static IFoo * CreateInstance( ); // implemented in IFoo.cpp, just returns new Foo
virtual void DoStuff() = 0;
virtual ~IFoo() {}
};
// A.h
class Foo : public IFoo {
public:
virtual void DoStuff();
private:
B::Bar Data; // B::Data comes from library B
};
You can go to settings and add the directory to the additional include directory's and you can just use the header by name.

Resources