从LPVOID转换为结构 - C

时间:2010-03-11 18:30:21

标签: c winapi

我正在编写一个简单的控制台应用程序,它允许我从通过我提供的参数传递的一组参数中创建一些线程。

DWORD WINAPI ThreadFunc(LPVOID threadData)
{
}

我将它们打包到一个结构中,并将它们作为参数传递给CreateThread方法,并尝试通过将它们从LPVOID转换为与我的结构相同的类型来解压缩它们。

我不知道如何在完成它之后将它强制转换为结构,所以我可以在方法本身中使用它,我尝试了各种组合(例如attatched)但它不会编译。

STRUCT:

#define numThreads 1

struct Data
{
    int threads;
    int delay;
    int messages;
};

致电方法:

HANDLE hThread;
    DWORD threadId;
    struct Data *tData;

    tData->threads = numThreads;
    tData->messages = 3;
    tData->delay = 1000;


    // Create child thread
    hThread = CreateThread(
                            NULL,       // lpThreadAttributes (default)
                            0,          // dwStackSize (default)
                            ThreadFunc, // lpStartAddress
                            &tData,     // lpParameter
                            0,          // dwCreationFlags
                            &threadId   // lpThreadId (returned by function)
                           );

我的尝试:

DWORD WINAPI ThreadFunc(LPVOID threadData)
    {
        struct Data tData = (struct Data)threadData;

        int msg;

        for(msg = 0; msg<5; msg++)
        {
            printf("Message %d from child\n", msg);
        }
        return 0;
}

编译错误:

错误C2440:'type cast':无法从'LPVOID'转换为'数据'

正如您所看到的,我已经实现了一种循环遍历大量消息的方法,我正在尝试使事情略微更高级并添加一些其他功能。

7 个答案:

答案 0 :(得分:9)

好的,对于初学者来说,这将会爆发:

struct Data *tData;

tData->threads = numThreads;
tData->messages = 3;
tData->delay = 1000;

...因为您已经创建了一个类型为'指向结构的指针'的变量,但是您还没有将指针初始化为指向任何东西。 tData未初始化,因此您正在写入野指针

你可能想要这样的东西:

// Allocate memory for the struct on the heap
struct Data *tData = malloc( sizeof(struct Data) );

// Initialize _all_ fields of the struct (malloc won't zero fill)
tData->threads = numThreads;
tData->messages = 3;
tData->delay = 1000;

其次,您传递tData地址(内存中tData变量所在的位置),而不是内存中{{1}的位置} 指向

tData

您可能希望传递指针的值(它指向的结构的地址):

// Create child thread
hThread = CreateThread( ...,
                        &tData, // OOPS - ADDRESS OF THE POINTER VARIABLE ITSELF!
                        ... );

当你在回调函数中收到struct的地址时,将它强制转换回原始的指针结构类型,取消引用并享受:

// Create child thread
hThread = CreateThread( ...,
                        tData,  // Value of the pointer
                        ... );

答案 1 :(得分:4)

首先,您只创建一个指向结构而不是结构本身的指针,然后使用未初始化的指针。

struct Data *tData;

tData->threads = numThreads;
tData->messages = 3;
tData->delay = 1000;

您需要创建一个结构。如果创建线程的函数将在线程完成之前退出,那么您需要动态创建它。 e.g。

struct Data *tData = malloc(sizeof *tData);

你应该确保在其他地方的适当位置释放结构,如果它没有在其他地方使用,可能在线程函数的末尾。

然后尝试将LPVOID参数强制转换为结构,其中您传递的是指向结构的指针。该参数不会大到足以按值传递整个结构。您可能只希望传入指向结构的指针(传入tData而不是&tData传递给CreateThread,然后您可以从LPVOID初始化为指向结构的指针。(因为这是C,不需要演员表,你应该避免不必要的演员表 - 不正确的演员表可以掩盖真正的错误。)

e.g。

struct Data *tData = threadData;

答案 2 :(得分:3)

LPVOID作为指向结构的指针而不是结构本身。所以你想要的东西是:

struct Data * ptData = (struct Data *)threadData;

然后您需要使用->运算符访问字段:

blahblah = ptData->messages;

但是。当你填充它时,你也缺少为结构分配的存储空间,因为你正在使用没有任何后备内存的指针。你需要malloc结构。您应该阅读C中的内存管理。(在许多其他链接中,this one讨论结构)

答案 3 :(得分:1)

您正在尝试将指针值(LPVOID等效于void*)转换为非指针值。这是不允许的。相反,您需要将其转换为不同的指针值,例如struct Data*

尝试以下

struct Data* pData = (struct Data*)threadData;

答案 4 :(得分:0)

将您的数据作为LPVOID

投射到CreateThread函数中
hThread = CreateThread(
                        NULL,       // lpThreadAttributes (default)
                        0,          // dwStackSize (default)
                        ThreadFunc, // lpStartAddress
                        (LPVOID)tData,     // lpParameter
                        0,          // dwCreationFlags
                        &threadId   // lpThreadId (returned by function)
                       )

同样在ThreadFunc中,Data应该是Data *

如果你去了LPVOID的定义,你会发现它只是指向虚空的指针。因为tData已经是一个指针,所以你不需要指针的地址。

答案 5 :(得分:0)

替换为:

struct Data *tData = (struct Data*)threadData; 

答案 6 :(得分:0)

您的代码中还有其他错误... tData似乎没有分配..也是您使用&amp;地址运算符传递它,因此您传递指针的地址而不是指针。可能当你得到指针并使用它时,你得到一个AccessViolation