Вызов PThread из класса формы Windows для функции внутри класса формы Windows - PullRequest
0 голосов
/ 31 марта 2012

Я использую pthread в форме Windows в Visual Studio 2008 Professional, но я получаю сообщение об ошибке в строке, которую я показываю в примере источника.Возможно, потому что это C ++ / CLI, потому что это обычно работает в обычных классах.Проблема в этой строке:

((TestGUI *) context) -> TestxFunc ();

в функции StaticCallFunc

public ref class TestGUI : public System::Windows::Forms::Form {
        /...
    public:

void TestxFunc(std::string test, std::string test2){
        this->btn_next->Enabled = false;
        cout << "HI, Test: " << test << "," << " Test 2: " << test2 << endl;

 }

static void *StaticCallFunc(void *context){
    std::string test = "foo";
    std::string test2 = "bar";
    printf("\nStarting Thread");
    ((TestGUI*)context)->TestxFunc(); //Line with the error down.
    return 0;

} 

System::Void tester_Click(System::Object^  sender, System::EventArgs^  e) {
      pthread_t t;
      pthread_create(&t, NULL, &TestGUI::StaticCallFunc, this);
}

//...

ошибка C3699: '': невозможно использовать это косвенное указание для компилятора типа 'Test :: TestxFunc' 1>, заменяющего '*' на '^' для продолжения анализа

ошибка C2227: слева от '->TestxFunc 'должен указывать на класс / struct / union / generic type

что мне сделать, чтобы это исправить?Этот вызов обычно работает в обычных классах, но в Windows Form он действительно не

1 Ответ

0 голосов
/ 31 марта 2012

Поскольку 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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...