在动态连接库上运用Thread Local Storage

最近在msdn查阅:Using Thread Local Storage in a dynamic-link library一文(http://msdn.microsoft.com/en-us/library/ms686997(v=VS.85).aspx),被此举的例子吓了一跳,随后赶紧写了个小程序,才知道例子程序运用extern来试图声明.dll里导出的函数,然后直接使用是完全不正确的。 这完全是一种想当然的做法。

我对其进行了更正:

// TestDll.dll的生成:

// The DLL code

#include <windows.h>

static DWORD dwTlsIndex; // address of shared memory

// DllMain() is the entry-point function for this DLL.

BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle
    DWORD fdwReason,                    // reason called
    LPVOID lpvReserved)                 // reserved
{
    LPVOID lpvData;
    BOOL fIgnore;

    switch (fdwReason)
    {
        // The DLL is loading due to process
        // initialization or a call to LoadLibrary.

        case DLL_PROCESS_ATTACH:

            // Allocate a TLS index.

            if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
                return FALSE;

            // No break: Initialize the index for first thread.

        // The attached process creates a new thread.

        case DLL_THREAD_ATTACH:

            // Initialize the TLS index for this thread.

            lpvData = (LPVOID) LocalAlloc(LPTR, 256);
            if (lpvData != NULL)
                fIgnore = TlsSetValue(dwTlsIndex, lpvData);

            break;

        // The thread of the attached process terminates.

        case DLL_THREAD_DETACH:

            // Release the allocated memory for this thread.

            lpvData = TlsGetValue(dwTlsIndex);
            if (lpvData != NULL)
                LocalFree((HLOCAL) lpvData);

            break;

        // DLL unload due to process termination or FreeLibrary.

        case DLL_PROCESS_DETACH:

            // Release the allocated memory for this thread.

            lpvData = TlsGetValue(dwTlsIndex);
            if (lpvData != NULL)
                LocalFree((HLOCAL) lpvData);

            // Release the TLS index.

            TlsFree(dwTlsIndex);
            break;

        default:
            break;
    }

    return TRUE;
    UNREFERENCED_PARAMETER(hinstDLL);
    UNREFERENCED_PARAMETER(lpvReserved);
}

// The export mechanism used here is the __declspec(export)
// method supported by Microsoft Visual Studio, but any
// other export method supported by your development
// environment may be substituted.

#ifdef __cplusplus    // If used by C++ code,
extern "C" {          // we need to export the C interface
#endif

__declspec(dllexport)
BOOL WINAPI StoreData(DWORD dw)
{
   LPVOID lpvData;
   DWORD * pData;  // The stored memory pointer

   lpvData = TlsGetValue(dwTlsIndex);
   if (lpvData == NULL)
   {
      lpvData = (LPVOID) LocalAlloc(LPTR, 256);
      if (lpvData == NULL)
         return FALSE;
      if (!TlsSetValue(dwTlsIndex, lpvData))
         return FALSE;
   }

   pData = (DWORD *) lpvData; // Cast to my data type.
   // In this example, it is only a pointer to a DWORD
   // but it can be a structure pointer to contain more complicated data.

   (*pData) = dw;
   return TRUE;
}

__declspec(dllexport)
BOOL WINAPI GetData(DWORD *pdw)
{
   LPVOID lpvData;
   DWORD * pData;  // The stored memory pointer

   lpvData = TlsGetValue(dwTlsIndex);
   if (lpvData == NULL)
      return FALSE;

   pData = (DWORD *) lpvData;
   (*pdw) = (*pData);
   return TRUE;
}
#ifdef __cplusplus
}
#endif
避免名字冲突最好还是用.def文件

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

#include

 

<windows.h>

#include

 

<stdio.h>

#include

 

<iostream>

using

 

namespace std;

#define

 

THREADCOUNT 4

#define

 

DLL_NAME TEXT("TestDll.dll")

VOID

 

 

ErrorExit ( LPSTR

);

typedef

 

 

BOOL ( WINAPI * MYPROCSET )( DWORD

);

typedef

 

 

BOOL ( WINAPI * MYPROCGET )( DWORD

*);

MYPROCSET

 

 

ProcStoreData

;

MYPROCGET

 

 

ProcGetData

;

DWORD

 

 

WINAPI ThreadFunc ( VOID

)

{

 

 

int i

;

 

 

if (! ProcStoreData ( GetCurrentThreadId

()))

 

 

ErrorExit ( "StoreData error"

);

 

 

for ( i =0; i < THREADCOUNT ; i

++)

{

 

 

DWORD dwOut

;

 

 

if (! ProcGetData (& dwOut

))

 

 

ErrorExit ( "GetData error"

);

 

 

if ( dwOut != GetCurrentThreadId

())

 

 

printf ( "thread %d: data is incorrect (%d)/n" , GetCurrentThreadId (), dwOut

);

 

 

else printf ( "thread %d: data is correct/n" , GetCurrentThreadId

());

 

 

Sleep

(0);

}

 

 

return

0;

}

int

 

 

main ( VOID

)

{

 

 

DWORD IDThread

;

 

 

HANDLE hThread [ THREADCOUNT

];

 

 

int i

;

 

 

HMODULE hm

;

 

 

// Load the DLL

 

 

 

hm = LoadLibrary ( DLL_NAME

);

 

 

if (! hm

)

{

 

 

ErrorExit ( "DLL failed to load"

);

}

// 不能简单的声明:

//extern "C" BOOL WINAPI StoreData(DWORD dw);
//extern "C" BOOL WINAPI GetData(DWORD *pdw);

 

 

ProcStoreData = ( MYPROCSET )( GetProcAddress ( hm , "StoreData" ));

 

 

ProcGetData = ( MYPROCGET )( GetProcAddress ( hm , "GetData" ));

 

 

// Create multiple threads.

 

 

for ( i = 0; i < THREADCOUNT ; i

++)

{

 

 

hThread [ i ] = CreateThread ( NULL ,

// default security attributes

0,

 

// use default stack size

(

 

LPTHREAD_START_ROUTINE ) ThreadFunc ,

// thread function

 

 

NULL ,

// no thread function argument

0,

 

// use default creation flags

&

 

IDThread );

// returns thread identifier

 

 

// Check the return value for success.

 

 

if ( hThread [ i ] == NULL

)

 

 

ErrorExit ( "CreateThread error/n"

);

}

 

 

WaitForMultipleObjects ( THREADCOUNT , hThread , TRUE , INFINITE

);

 

 

FreeLibrary ( hm

);

 

 

cin . get

();

 

 

return

0;

}

VOID

 

 

ErrorExit ( LPSTR lpszMessage

)

{

 

 

fprintf ( stderr , "%s/n" , lpszMessage

);

 

 

ExitProcess

(0);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值