jak zwykle autor watku zapomnial podac najwazniejszej rzeczy..
jakby(ś) raczyl zalaczyc jakis komunikat bledu, tez bysmy Ci od razu odpowiedzieli o co chodzi..
a chodzi o fragmenty kodu:
#pragma once
#include <iostream>
#include "DeviceManager.h"
#include <boost/thread/thread.hpp>
namespace reciver_in_form {
public ref class Form1 : public System::Windows::Forms::Form
{
....
private: System::Void nasluchuj_Click(System::Object^ sender, System::EventArgs^ e) {
.....
boost::thread thrd(boost::bind(&listenForPacket,this));
thrd.join();
}
private: void listenForPacket(){
......
}
}
...no i wszystko jasne. probujesz operowac na ref-class'ie..
BOOST NIE WSPOLPRACUJE Z C++/CLI
BOOST jest biblioteka C++, nie C++/CLI.
C++/CLI to jeden, a C++ to drugi świat.
nie uda Ci sie takie pomieszanie ani żadne inne podobne, poniewaz NIE MOZNA TRZYMAC REFERENCJI/a tymbardziej jako wartosc/ do obiektow ref- w obiektach ktore ref- nie sa. i kropka. takie jest ograniczenie c++/cli. uznaj ze jest ulomny i tego nie potrafi. bądźmy wdzieczni że przynajmniej potrafi w druga strone...
i z tego powodu, nie mozesz uzyc boost::bind na metodzie z ref-class -- boost::bind probuje zapamietac ptr-na-metode oraz ptr-na-obiekt i to wrecz unmanagedptr-na-obiekt wiec w przypadku gdy podajesz mu ref-class to to sie podwojnie nie ma prawa udac!!
szybki proof:
#pragma once
namespace blah {
using namespace System;
using namespace System::Collections;
using namespace System::Windows::Forms;
public ref class Form1 : public System::Windows::Forms::Form
{
};
class Test
{
Form1^ form;
};
}
kompilacja:
1>------ Build started: Project: 141243, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>.\main.cpp(21) : error C3265: cannot declare a managed 'form' in an unmanaged 'reciver_in_form::Test'
1> may not declare a global or static variable, or a member of a native type that refers to objects in the gc heap
1>Build log was saved at "file://c:\poligon\4p\141243\Debug\BuildLog.htm"
1>141243 - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
jesli wiec chcesz uzywac boost::thread, Twoja docelowa metoda do odpalenia musi byc z klasy zwyklej, natywnej, nie-ref.
#pragma once
#include <boost/bind.hpp>
#include <boost/thread.hpp>
namespace blah {
using namespace System;
using namespace System::Collections;
using namespace System::Windows::Forms;
struct Test
{
void threadproc(){}
};
public ref class Form1 : public System::Windows::Forms::Form
{
void test()
{
Test obiekt; //1
boost::thread thr(boost::bind(&Test::threadproc, obiekt));
thr.join(); //3
} //2
};
}
przyczym, oczywiscie MUSI SIE uwazac na czasy życia obiektow native. obiekt utworzony w (1) rozplynie sie w powietrzu w momencie (2), wiec (3) musi byc przed ta chwila, inaczej watek straci swoj "kontekst".. nie mozesz wiec zaczac w ten sposob watku w metodzie button1_onclick a join w button2_onclick..
szczesliwie klasy ref- potrafia trzymac unmanaged-ptr (ale wartosci juz nie! heh, patrz (*) ), wiec ten problem mozesz rozwiazac prosto np. tak:
#pragma once
#include <boost/bind.hpp>
#include <boost/thread.hpp>
namespace blah {
using namespace System;
using namespace System::Collections;
using namespace System::Windows::Forms;
struct Test
{
void threadproc(){}
};
public ref class Form1 : public System::Windows::Forms::Form
{
Test* obiekt; //* - musisz trzymac 'Test*'. proba utworzenia pola typu 'Test' sie nie uda w ref-class.
boost::thread* thr;
void test()
{
obiekt = new Test();
thr = new boost::thread(boost::bind(&Test::threadproc, obiekt));
}
void detest()
{
thr->join();
delete thr;
delete obiekt;
}
int pole;
void metoda()
{
}
};
}
oczywiscie, klasa Test kompletnie nieswiadoma istnienia klasy Form, wiec nie da rady wywolac z niej zadnej "metody", ani dostac sie do zadnego pola.
..tak wiec thread proc'a musisz uswiadomic i definicja klasy Form i OBIEKTEM Form..
..tylko jak biedny Test albo Bind sobie przechowa ref do obiektu Form?
jesli wiec operujesz na C++/CLI, przyzwyczaj sie do uzywania CLI i .Net. zapoznaj sie z System.Threading.Thread i uzyj go do opakowywania watkow ktore musza operowac na obiektach ref-class. oszczedzisz sobie bólu głowy..
..o ktory moze kogos przyprawiac takie cos:
#pragma once
#include <string>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
namespace blah {
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Windows::Forms;
struct Test
{
Test(size_t h) : handle(h) {}
void threadproc();
size_t handle;
};
public ref class Manager
{
private:
static Dictionary<size_t, Object^>^ niechcesztaktegorobic = gcnew Dictionary<size_t, Object^>();
public:
static size_t Register(Object^ obj)
{
size_t handle = 0; //random.. whatever unique..
niechcesztaktegorobic->Add(handle, obj);
//i przydaloby sie reagowac wy-rejestrowaniem na event obj->Disposed, itp..
return handle;
}
template<class T> static T^ Get(size_t handle)
{
Object^ obj;
if(!niechcesztaktegorobic->TryGetValue(handle, obj))
return nullptr;
return dynamic_cast<T^>(obj);
}
};
public ref class Form1 : public System::Windows::Forms::Form
{
Test* obiekt;
boost::thread* thr;
size_t myHandle;
void test()
{
myHandle = Manager::Register(this);
obiekt = new Test(myHandle);
thr = new boost::thread(boost::bind(&Test::threadproc, obiekt));
}
void detest()
{
thr->join();
delete thr;
delete obiekt;
// Manager::Unregister(this, handle);
}
public:
int pole;
void metoda()
{
}
};
void Test::threadproc()
{
Form1^ ptr = Manager::Get<Form1>(handle);
ptr->pole = 5;
ptr->metoda();
}
}