Поскольку TestGUI
является классом CLI / C ++, вы должны использовать ^
, а не *
для разыменования его указателя, но это не единственная проблема. Кажется, вы хотите выполнить метод члена класса CLI / C ++ в pthread. Чтобы заставить его работать, вы можете попробовать следующий способ:
* Удалите StaticCallFunc
из TestGUI
класса и сделайте его глобальным методом.
* Чтобы передать TestGUI
указатель на неуправляемую функцию, вы можете использовать gcroot
. Так определите класс контейнера, например PtrContainer
который имеет gcroot
в качестве члена.
//dont forget forward declerations
void *StaticCallFunc(void *context); //forward decleration
ref class TestGUI; //forward decleration
//Define a simple argument class to pass pthread_create
struct PtrContainer{
gcroot<TestGUI^> guiPtr; //you need to include vcclr.h for this
};
Когда вы связываетесь с pthread_create
, вы можете использовать PtrContainer
как следующее:
System::Void tester_Click(System::Object^ sender, System::EventArgs^ e) {
//init. container pointer,
//we use dynamically allocated object because the thread may use it after this method return
PtrContainer* ptr = new PtrContainer;
ptr->guiPtr = this;
pthread_t t;
pthread_create(&t, NULL, StaticCallFunc, ptr );
}
И вы должны удалить указатель контейнера внутри метода драйвера (StaticCallFunc
) после того, как с ним покончено:
void *StaticCallFunc(void *context){
std::string test = "foo";
std::string test2 = "bar";
printf("\nStarting Thread");
PtrContainer* ptr = reinterpret_cast<PtrContainer*>(context);
ptr->guiPtr->TestxFunc(test, test2);
//dont forget to delete the container ptr.
delete ptr;
return 0;
}
Еще одна заметка; когда вы обращаетесь к компоненту .NET GUI многопоточным способом, вы должны быть осторожны, чтобы вызывать ваши элементы управления в поточно-ориентированном режиме.
Изменить: я добавил следующий полный исходный код, который компилируется и работает под Visual Studio 11, Windows7.
//sample.cpp
#include <iostream>
#include <string>
#include <vcclr.h>
#include <sstream>
using namespace std;
using namespace System;
using namespace System::Windows::Forms;
#include "pthread.h"
#include <stdio.h>
#define PTW32_THREAD_NULL_ID {NULL,0}
#define int64_t _int64
void *StaticCallFunc(void *context); //forward decleration
ref class TestGUI; //forward decleration
//Define a simple argument class to pass pthread_create
struct PtrContainer{
gcroot<TestGUI^> guiPtr; //you need to include vcclr.h for this
};
ref class TestGUI : public System::Windows::Forms::Form
{
public:
TestGUI(void) {
this->Click += gcnew System::EventHandler(this, &TestGUI::tester_Click );
}
void TestxFunc(std::string test, std::string test2){
cout << "HI, Test: " << test << "," << " Test 2: " << test2 << endl;
}
System::Void tester_Click(System::Object^ sender, System::EventArgs^ e) {
//init. container pointer,
//we use dynamically allocated object because the thread may use it after this method return
PtrContainer* ptr = new PtrContainer;
ptr->guiPtr = this;
pthread_t t;
pthread_create(&t, NULL, StaticCallFunc, ptr );
}
};
void *StaticCallFunc(void *context){
std::string test = "foo";
std::string test2 = "bar";
printf("\nStarting Thread");
PtrContainer* ptr = reinterpret_cast<PtrContainer*>(context);
ptr->guiPtr->TestxFunc(test, test2);
//dont forget to delete the container ptr.
delete ptr;
return 0;
}
int main()
{
TestGUI^ testGui = gcnew TestGUI();
testGui->ShowDialog();
return 0;
}
Составлено с:
/analyze- /clr /Od /nologo /MDd /Gm- /Fa".\Debug\" /I".." /Oy- /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.dll" /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Forms.dll" /Zc:forScope /Fo".\Debug\" /Gy- /Fp".\Debug\Debug.pch" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "CLEANUP_C" /D "_VC80_UPGRADE=0x0600" /D "_MBCS" /WX /errorReport:queue /GS /Fd".\Debug\" /fp:precise /FR".\Debug\" /W3 /Z7 /Zc:wchar_t /EHa