青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

concentrate on c/c++ related technology

plan,refactor,daily-build, self-discipline,

  C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
  37 Posts :: 1 Stories :: 12 Comments :: 0 Trackbacks

常用鏈接

留言簿(9)

我參與的團隊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

#

我在MSVC6里的win32 console工程里面寫了一段這樣的代碼,已經(jīng)去掉了不必要的代碼已達到注意重點地目點:
#include  <winbase.h>
#include  <windows.h>
switch( dwWaitResult = ::SignalObjectAndWait(
                                   m_hLogItemSendEvent,
                                   m_hLogItemReceivedEvent,
                                   MUTEX_LOCK_TIMEOUT,
                                   FALSE ) )
    {
    case WAIT_OBJECT_0:
               ::ResetEvent( m_hLogItemReceivedEvent );
               ::ResetEvent( m_hLogItemSendEvent );
    break;
    case WAIT_TIMEOUT:
    throw AutoLock::CAutoLockTimeoutExc( MUTEX_LOCK_TIMEOUT * 10 );
    break;
    default:
    throw AutoLock::CAutoLockWaitExc( dwWaitResult, ::GetLastError() );
    }
編譯以后,得到以下兩個錯誤:

error C2039: 'SignalObjectAndWait' : is not a member of '`global namespace''
error C2065: 'SignalObjectAndWait' : undeclared identifier

我在msdn上面已經(jīng)查找到了SignalObjectAndWait在winbase里面聲明,而在windows里面定義的。但是我在上面的代碼片斷里面已經(jīng)給出了相關(guān)頭文件。卻在編譯的時候出現(xiàn)兩個錯誤。

問題解決如下:
#if(_WIN32_WINNT >= 0x0400)
WINBASEAPI
DWORD
WINAPI
SignalObjectAndWait(
    IN HANDLE hObjectToSignal,
    IN HANDLE hObjectToWaitOn,
    IN DWORD dwMilliseconds,
    IN BOOL bAlertable
    );
#endif /* _WIN32_WINNT >= 0x0400 */
在我英文操作系統(tǒng)里面的版本過低,導(dǎo)致出現(xiàn)無法進入上述條件編譯里面,因此需要做的事情是,要么將條件編譯注釋掉,其實問題也不大,反正以后也不會有什么變動,要么就是在stdafx.h最前面重新定義一個_WIN32_WINNT,并且這個定義值應(yīng)該要大于或者等于0x0400.這樣才是okay的。
一些其他信息:
http://topic.csdn.net/u/20080429/16/c12ef43a-5eba-435e-b0bf-f49233cf1d5e.html
http://www.codeguru.com/forum/showthread.php?t=451931


posted @ 2008-04-29 19:38 jolley 閱讀(732) | 評論 (0)編輯 收藏

在vc6里面一般都沒有這個頭文件的,在后面的版本(.NET)都有相關(guān)的說明,不過這個是CString包含的頭文件,我之前將open source的代碼移植到win32 application平臺下面,對方的編譯器是vc2003,而我的是用到了vc6,所以就遇到這個問題了,解決辦法有兩種:
1)在工程里面加入MFCsupport,因為CString是MFC里面的內(nèi)容。具體做法是project/settings/General/microsoft foundation class處選擇using MFC as a shared dll./ static library.
在msdn上面有具體的說明。
可能看起來比較麻煩,不過不好意思,就這樣弄過來防止msdn上面這個文章過舊了,又被刪除了。

給 ATL EXE 項目添加 MFC 支持



1. 在包括 Atlbase.h 之前,將以下 #include 指令添加到 StdAfx.h:
      #include <afxwin.h>   // MFC core and standard components
            #include <afxext.h>   // MFC extensions
            #include <afxdisp.h>  // MFC Automation extensions
2. 更改項目設(shè)置以使用 MFC。 在 Project Settings 對話框中,單擊 General 選項卡,然后將 Microsoft Foundation Classes 列表框中的設(shè)置更改為 MFC。
3. 添加 CWinApp 衍生類,并聲明一個該類型的全局變量,如下所示:
class CMyApp : public CWinApp
            {
            public:
            virtual BOOL InitInstance();
            virtual int ExitInstance();
            protected:
            BOOL m_bRun;
            };
4. 用以下 InitInstance 和 ExitInstance 代碼替換 _tWinMain 函數(shù):
BOOL CMyApp::InitInstance()
            {
            // Initialize OLE libraries.
            if (!AfxOleInit())
            {
            AfxMessageBox(_T("OLE Initialization Failed!"));
            return FALSE;
            }
            // Initialize CcomModule.
            _Module.Init(ObjectMap, m_hInstance);
            _Module.dwThreadID = GetCurrentThreadId();
            // Check command line arguments.
            TCHAR szTokens[] = _T("-/");
            m_bRun = TRUE;
            LPCTSTR lpszToken = FindOneOf(m_lpCmdLine, szTokens);
            while (lpszToken != NULL)
            {
            // Register ATL and MFC class factories.
            if (lstrcmpi(lpszToken, _T("Embedding"))==0 ||
            lstrcmpi(lpszToken, _T("Automation"))==0)
            {
            AfxOleSetUserCtrl(FALSE);
            break;
            }
            // Unregister servers.
            // There is no unregistration code for MFC
            // servers. Refer to <LINK TYPE="ARTICLE" VALUE="Q186212">Q186212</LINK> "HOWTO: Unregister MFC
            // Automation Servers" for adding unregistration
            // code.
            else if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
            {
            VERIFY(SUCCEEDED(_Module.UpdateRegistryFromResource(IDR_ServerS2B, FALSE)));
            VERIFY(SUCCEEDED(_Module.UnregisterServer(TRUE)));
            m_bRun = FALSE;
            break;
            }
            // Register ATL and MFC objects in the registry.
            else if (lstrcmpi(lpszToken, _T("RegServer"))==0)
            {
            VERIFY(SUCCEEDED(_Module.UpdateRegistryFromResource(IDR_ServerS2B, TRUE)));
            VERIFY(SUCCEEDED(_Module.RegisterServer(TRUE)));
            COleObjectFactory::UpdateRegistryAll();
            m_bRun = FALSE;
            break;
            }
            lpszToken = FindOneOf(lpszToken, szTokens);
            }
            if (m_bRun)
            {
            // Comment out the next line if not using VC 6-generated
            // code.
            _Module.StartMonitor();
            VERIFY(SUCCEEDED(_Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE)));
            VERIFY(COleObjectFactory::RegisterAll());
            // To run the EXE standalone, you need to create a window
            // and assign the CWnd* to m_pMainWnd.
            LPCTSTR szClass = AfxRegisterWndClass(NULL);
            m_pMainWnd = new CWnd;
            m_pMainWnd->CreateEx(0, szClass, _T("SomeName"), 0, CRect(0, 0, 0, 0), NULL, 1234);
            }
            return TRUE;
            }
            int CMyApp::ExitInstance()
            {
            // MFC's class factories registration is
            // automatically revoked by MFC itself.
            if (m_bRun)
            {
            _Module.RevokeClassObjects();
            Sleep(dwPause); //wait for any threads to finish
            }
            _Module.Term();
            return 0;
            }
5. 對于 Unicode 版本,請確保進入點被設(shè)置為 wWinMainCRTStartup,該設(shè)置在 Project Settings 對話框中 Link 字段的 Output 類別中。 有關(guān)其它信息,請參見 Microsoft Knowledge Base 中的下列文章:
125750 (http://support.microsoft.com/kb/125750/EN-US/) PRB: 錯誤 LNK2001: “_WinMain@16”: 不能解析的外部符號
6. 將以下代碼行添加到 COM 接口、窗口過程和導(dǎo)出函數(shù)的每個成員函數(shù)的開頭:
AFX_MANAGE_STATE(AfxGetAppModuleState());
有關(guān) AFX_MANAGE_STATE 的詳細信息,請查詢 VC++ 聯(lián)機文檔。
有關(guān)將 MFC 支持添加到 ATL COM AppWizard 項目的詳細信息,請參見下面的 Microsoft Knowledge Base 文章:

181505 (http://support.microsoft.com/kb/181505/EN-US/) PRB: ATL COM AppWizard 不提供對 .EXE 的 MFC 支持

回到頂端

將 MFC 支持添加到 ATL DLL 項目



執(zhí)行上面的步驟 1 到步驟 3。

1. 將 AppWizard 生成的 DllMain 的 DLL_PROCESS_ATTACH 和 DLL_PROCESS_DETACH 中的代碼移到 CMyApp 的 InitInstance 和 ExitInstance,并刪除 DllMain,如下所示:
      BOOL CMyApp::InitInstance()
            {
            _Module.Init(ObjectMap, m_hInstance);
            return CWinApp::InitInstance();
            }
            int CMyApp::ExitInstance()
            {
            // MFC's class factories registration is
            // automatically revoked by MFC itself.
            if (m_bRun)
            _Module.RevokeClassObjects();
            
2. 將以下代碼行添加到 COM 接口、窗口過程和導(dǎo)出函數(shù)的每個成員函數(shù)的開頭:
AFX_MANAGE_STATE(AfxGetStaticModuleState());
有關(guān)其它信息,請參見 Microsoft Knowledge Base 中的下列文章:
140850 (http://support.microsoft.com/kb/140850/EN-US/) HOWTO: 轉(zhuǎn)換 DLLTRACE 以使用共享庫中的 MFC

另外一種辦法就是將atlstr廢掉,采用其他辦法
因為atlstr實際起作用的是CString,而如果能夠找到CString的替代方案,就可以了。
替代方案在這里:
http://www.codeguru.com/forum/showthread.php?t=402543
一般建議用std::string來完成這些不依賴微軟某種技術(shù)的做法。
在我的項目里面,因為采用的是win32 application工程,并且該項目已經(jīng)很大了,不想因為這個而在那里增加一些方案1的處理,我采用了方案2。
posted @ 2008-04-29 10:14 jolley 閱讀(8299) | 評論 (0)編輯 收藏

進程1:

#define BUF_SIZE 256
char fileMapObjectName[] = "FileMappingObject";
class Sample
{
public:
 void set_x(int x){this->xx = x;}
 int get_x(){return this->xx;}
 Sample(){}
private:
 int xx;
};

class EmulatorWindow
{
public:
 void set_ew(Sample s){this->sample = s;}
 Sample get_ew(){return this->sample;}
 EmulatorWindow(){}
private:
 Sample sample;
};

int main()
{
 HANDLE fileMap = CreateFileMapping(
  (HANDLE)0xFFFFFFFF,
  NULL,
  PAGE_READWRITE,
  0,
  BUF_SIZE,
  fileMapObjectName);
 if (NULL == fileMap || GetLastError() == ERROR_ALREADY_EXISTS)
 {
  printf("create file mapping fails! the error code is (%d)",GetLastError());
  return 0;
 }
 Sample s;
 s.set_x(112);
 EmulatorWindow* buffer = (EmulatorWindow*)MapViewOfFile(
  fileMap,
  FILE_MAP_ALL_ACCESS,
  0,
  0,
  BUF_SIZE);
 if (NULL == buffer)
 {
  printf("mapping view of file fails! the error code is (%d)",GetLastError());
  return 1;
 }

 EmulatorWindow ew;
 ew.set_ew(s);

 CopyMemory(buffer,&ew,BUF_SIZE);
 getchar();

 FlushViewOfFile(fileMap,BUF_SIZE);

 UnmapViewOfFile(buffer);
 buffer = NULL;

 CloseHandle(fileMap);
 fileMap = NULL;
 
 return 2;
}  
進程2:
#define BUF_SIZE 256
char fileMapObjectName[] = "FileMappingObject";

class Sample
{
public:
 void set_x(int x){this->xx = x;}
 int get_x(){return this->xx;}
 Sample(){}
private:
 int xx;
};

class EmulatorWindow
{
public:
 void set_ew(Sample s){this->sample = s;}
 Sample get_ew(){return this->sample;}
 EmulatorWindow(){}
private:
 Sample sample;
};

int main()
{
 HANDLE fileMap = OpenFileMapping(
  FILE_MAP_ALL_ACCESS,
  TRUE,
  fileMapObjectName);
 if (NULL == fileMap)
 {
  printf("opening file mapping fails! the error code is (%d)",GetLastError());
  return 0;
 }
  
 EmulatorWindow* sharedMemory = (EmulatorWindow*)MapViewOfFile(
  fileMap,
  FILE_MAP_ALL_ACCESS,
  0,
  0,
  0);
 if (NULL == sharedMemory )
 {
  printf("mapping view of file fails! the error code is (%d)",GetLastError());
  return 1;
 }

 Sample s = sharedMemory->get_ew();
 int x = s.get_x();

 char buffer[100];
 memset(buffer,0,100);
 sprintf(buffer,"message box is:(%d)",x);
 MessageBox(NULL,buffer,NULL,MB_OK);

 UnmapViewOfFile(sharedMemory);
 sharedMemory = NULL;

 CloseHandle(fileMap);
 fileMap = NULL;

 return 3;

}
1)
這是兩個比較簡單的文件映射例子,其中進程1為源進程,而進程2為目的進程。進程1與進程2進行通信,并且共享一個窗口對象,記得在游戲里面會有很多窗口對象的,因此,在與游戲進行通信的時候就可以共享窗口對象。前段時間在做自動化測試的時候,就經(jīng)常要與客戶端進行一些交互操作,比如,獲得某個窗口的按鈕狀態(tài),以及文本的信息等,不過這樣做的代價是兩個進程要共享一部分頭文件,起碼像我兩個進程里面都用到了兩段相同的頭文件代碼,不然可能就出現(xiàn)某個窗口對象或者控件對象未聲明或者未定義。

2)
另外值得說明的是進程1里面的getchar()用法,很多時候,這個用來延遲操作,并且防止運行過快,特別是在很簡單的結(jié)果輸出中,結(jié)果會一閃而過,這個時候getchar就起作用了。這里的getchar所起的作用也是延遲的,不過如果將這個getchar()去掉的話,那么你就很可能得到GetLastError()錯誤代碼為2。ERROR_FILE_NOT_FOUND.這個原因是在建立文件對象以后,沒有一段時間緩沖的話,那么進程2有可能找不到在進程空間里面的文件映射,因此就會說ERROR_FILE_NOT_FOUND的錯誤。

3)
之前認為共享內(nèi)存嘛,應(yīng)該是可以共享任何對象的,但是我在共享一個deque的時候,發(fā)現(xiàn)錯了,后來才發(fā)現(xiàn)文件映射不能共享指針的,deque是STL的一個序列式容器,而其內(nèi)部都是一系列的指針組成的,后來在msdn上面發(fā)現(xiàn)了一段這樣的話,很震驚:

Do not store pointers in the memory mapped file; store offsets from the base of the file mapping so that the mapping can be used at any address.
可以共享的是非指針的用戶自定義類型, 以及內(nèi)建類型等,不包括含有指針的各種類型。


   


 

posted @ 2008-04-24 17:04 jolley 閱讀(1442) | 評論 (0)編輯 收藏

     摘要: 繪制管線
應(yīng)用程序階段
幾何階段 模型和視點變換/光照/投影/裁減/屏幕映射
光柵階段
  閱讀全文
posted @ 2008-04-24 09:12 jolley 閱讀(726) | 評論 (1)編輯 收藏

這回貼上來自codeguru上面的一篇討論,感覺很舒服:
   

I’ve created a very simple Win32 DLL. It only has one exported function called “Test” whose declaration looks like this:-

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif


MYDLL_API HRESULT Test(void);
Then in the source file:-

MYDLL_API HRESULT Test(void)
{
return (HRESULT) 66;
}


Now in my executable, I’ve done this:-

static HMODULE hDLL;
typedef HRESULT (STDAPICALLTYPE * LPFNTEST) (void);
LPFNTEST _pfnTest;

Then I load the DLL:-

hDLL = LoadLibrary("MyDLL.dll");

All the above works fine and hDLL gets a non-NULL value . Now I come to obtain the proc address for function “Test”:-

_pfnTest = (LPFNTEST)::GetProcAddress(hDLL, "Test");
but _pfnTest ends up as NULL and GetLastError() returns 127 (ERROR_PROC_NOT_FOUND). What have I done wrong?? I haven't implemented any code yet in DllMain(). For example, I haven't initialised anything. Should I have done?


Siddhartha

February 20th, 2006, 11:18 AM

but _pfnTest ends up as NULL and GetLastError() returns 127 (ERROR_PROC_NOT_FOUND). What have I done wrong?? You have not accounted for the name decoration that the VC++ Compiler has subjected your DLL's Exported Functions to.

To know exactly what it has done, open the DLL in Dependency Walker and observe exported function names...

www.dependencywalker.com (http://www.dependencywalker.com) (for latest version)
You either need to GetProcAddress of the functions using their decorated names, or better - create entries in your DLL Project's DEF File that define the names of the exported functions the way you would like to see them as.

Something like this -
LIBRARY "MYDLL"

EXPORTS
Test PRIVATE


Bornish

February 20th, 2006, 11:18 AM

Your function is exported using the C++ decorated name. Use extern "C" before the function prototype, or use a *.def file in your project containing:EXPORTS
TestTo know for sure that your function is exported with an undecorated name, use Dependency Viewer to list its exports.

Note: I've noticed another potential problem, which will not affect this test function since has no parameters, but your dll declares the function as __cdecl (depending on your project's default settings), and the exe tries to use it with STDAPICALLTYPE which I assume stands for __stdcall calling convention.

Regards,


John E

February 20th, 2006, 11:31 AM

Thanks guys. It's ages since I wrote a DLL. It's all starting to come back to me now!! :wave:


John E

February 23rd, 2006, 04:51 PM

Hmmm.... this still isn't quite right. According to this MSDN article (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/msmod_20.asp) the use of dllimport and dllexport should eliminate the need to specify exported functions in a module definition file (.DEF)

However, in my case, that's not working. I'm finding that I still need to list the functions as EXPORTS in a .DEF file - even though I'm correctly defining __declspec(dllimport) and __declspec(dllexport). Any ideas about what I might be doing wrong?


Paul McKenzie

February 23rd, 2006, 05:06 PM

Hmmm.... this still isn't quite right. According to this MSDN article (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/msmod_20.asp) the use of dllimport and dllexport should eliminate the need to specify exported functions in a module definition file (.DEF)Only if you are linking with the export library, in other words, you're using Visual C++ and you add the .lib to your project.

If you're using LoadLibrary() and GetProcAddress(), there is no .lib file to help the linker resolve the name. You must either use the *exact* name you see in the exported function list when you ran Dependency Walker, or you use a def file and rebuild your DLL to get a totally "clean" function name.

Regards,

Paul McKenzie


Bornish

February 23rd, 2006, 05:07 PM

If you use __declspec(dllexport) you don't need the def file.
In fact, with only a def file you might get into an ambiguous name situation (like it happen to me before), when a class declared a method with the same name of the global exported function. The solution was to use __declspec(dllexport) for the global function.
The problem we suggested you might have was that your function was exported with a C++ decorated name. Thus, you need to use extern "C" before __declspec(dllexport).
Got to go now... :)
Regards,


John E

February 23rd, 2006, 05:22 PM

Only if you are linking with the export library, in other words, you're using Visual C++ and you add the .lib to your project.You mean if I link statically, rather than dynamically?

Surely if I link statically, there's no need to mess about with dllimport and dllexport at all??


VladimirF

February 23rd, 2006, 05:28 PM

Paul wasn't talking about static link, he compared dynamic linking with on-demand GetProcAddress() call.


kirants

February 23rd, 2006, 05:36 PM

Hmmm.... this still isn't quite right. According to this MSDN article (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/msmod_20.asp) the use of dllimport and dllexport should eliminate the need to specify exported functions in a module definition file (.DEF)

However, in my case, that's not working.

I don't think that is the case. It is not working because you are doing a GetProcAddress with non-mangled name while using dllexport without using a def file causes name mangling and hence the failure.

The reason it works when you add the .def file with the names is because you are putting the name in unmangled form in it and that is what you are using in GetProcAddress.

So, summary si this:
if you use dllexport approach without def file, please understand that the Visual C++ compiler mangles the name and this is the form in which your function will be exported. For e.g. your Test function will be exported as , ?Test@XWZ or something of that form. So, if you do a GetProcAddress, make sure you use "?Test@XWZ" and not "Test".
If you use dllexport, but also supply a .def file with the undeclared names, the linker is gonna put that in the dll export section. So, you can now use GetProcAddress(hMod,"Test")
If you do use .def file, there is no need to use dllexport directive
If you do not want to use .def file and still want to use dllexport directive, wrap those functions with

extern "C"
{

}


kirants

February 23rd, 2006, 05:38 PM

You mean if I link statically, rather than dynamically?

A dll is always dynamically linked. What Paul was referring to was implicit linking versus explicit linking via LoadLibrary/GetprocAddress


John E

February 23rd, 2006, 05:48 PM

Thanks for the help. I did realise that the problem was because of decorated names. What I didn't realise was that I had to link to the lib if I used __declspec(dllexport).... I've managed to get it to work now, without the DEF file :wave:


kirants

February 23rd, 2006, 05:52 PM

What I didn't realise was that I had to link to the lib if I used __declspec(dllexport)
No. using dllexport does not mean you have to link to the .lib file.

Whether you use dllexport or def file, you will always be able to use LoadLibrary/GetProcAddress approach , provided you pass the right export name to GetProcAddress


John E

February 23rd, 2006, 05:55 PM

Oops... one other thing, just before I shoot myself in the foot...!

Ultimately, this DLL will be going to someone who'll be calling it from Visual Basic .NET. This means that my lib file would be useless to them. Therefore, I guess I'm better off sticking to the .DEF approach on this occasion because I don't really want the names to be mangled.


MikeAThon

February 23rd, 2006, 11:59 PM

A dll is always dynamically linked. What Paul was referring to was implicit linking versus explicit linking via LoadLibrary/GetprocAddress
I think that Microsoft refers to these as "run-time dynamic linking" vs. "load-time dynamic linking". See http://msdn.microsoft.com/library/en-us/dllproc/base/using_dynamic_link_libraries.asp

Mike


kirants

February 24th, 2006, 12:29 AM

Interesting, Mike.. ... Microsoft seems to be using different terms for the same :)

For e.g. see here
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_core_determine_which_linking_method_to_use.asp


MikeAThon

February 24th, 2006, 01:28 AM

You're right: that is the same thing, and Microsoft is using different terminology for it.

Mike


gopal.srini

February 24th, 2006, 02:49 AM

Hi

Continuing with this topic, could any one please tell me how to call a method from ddao35.dll, say - OpenDatabase whose return type is class- CdbDatabase - using __declspec( dllexport ), they have exported this function available in dbdao.h file

I tried the follwoing but in vain

typedef UINT (CALLBACK* LPFNDLLFUNC1)(LPCTSTR,BOOL,BOOL,LPCTSTR);
LPFNDLLFUNC1 lpfnDllFunc1;
char *get_ver = "?OpenDatabase@CdbDBEngine@@QAE?
AVCdbDatabase@@PBDHH0@Z";

if(hDLL)
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,"?OpenDatabase@CdbDBEngine@@QAE?AVCdbDatabase@@PBDHH0@Z");


if (!lpfnDllFunc1)
{
// handle the error
FreeLibrary(hDLL);
return 0;
}
else
{
lpfnDllFunc1("TestDB.mdb",0L,FALSE,NULL);
printf("success");

}

I am getting unhandled exception in my.exe(ddao35.dll) 0xc0000005 Access violation

Any help?

Regards
Gopal


kirants

February 24th, 2006, 03:40 AM

gopal.srini, please start a new thread, since this seems to be a different problem and unrelated to the original question


gopal.srini

February 24th, 2006, 04:09 AM

ok..sorry..

Thanks
Gopal


wshcdr

February 24th, 2006, 01:09 PM

To use LoadLibrary(...),GetProcAddr(...) ,you must write a DEF file,


Bornish

February 25th, 2006, 09:56 AM

To use LoadLibrary(...),GetProcAddr(...) ,you must write a DEF file, :eek: This is somehow correct, if one needs undecorated names to be exported.
I thought using __declspec(dllexport) can eliminate the need of a *.def file. :blush:
I've tried exporting a function Test from a DLL that doesn't make use of a def file, so I've wrote this:extern "C" __declspec(dllexport) int __stdcall Test(int x) {
return ++x;
}The result was an export named _Test@4 (C++ decorated), thus extern "C" having no effect. I've tried several other variations... even using the obselete keyword _export in a *.c file instead of a *.cpp file. Still didn't find a way to export my function as Test without using a def file. It seems to be the only way to define alias names when exporting functions or to export only by ordinal (NONAME)... else you'll get the C++ decorated name _Test@4.
Conclusion:
If you don't care less about the name used in GetProcAddress, then you don't need a def file... else, use a def and keep your _declspec(dllexport) to avoid ambiguities. An article from MSDN recomends writing in a def file both the alias name and the decorated name to avoid ambiguities:EXPORTS
Test = _Test@4This way, when another namespace or class defines a function Test, the linker won't have a dilemma in choosing the function to export.
Best regards,


John E

February 25th, 2006, 10:21 AM

You've pretty much confirmed what I found myself. The only way to guarantee that the names don't get decorated is to put them in a .DEF file.

If you go the __declspec(dllexport) route - together with __declspec(dllimport) - then, providing you use Paul's suggestion of linking to the DLL's associated lib file, you can call the functions as though they weren't decorated - but in fact, they still are.

I assume that what the lib must do is simply to translate calls to each function's undecorated name into the corresponding call with the decorated name.

 

 

 

posted @ 2008-04-02 16:29 jolley 閱讀(491) | 評論 (0)編輯 收藏

 

今天第一次寫DLL

DLL里面有三種類型,win32 DLL, 標準MFC DLL,以及非標準MFC DLL

他們的區(qū)別是,win32 DLL里面主要是用C/C++編寫的,不能調(diào)用MFC里面的函數(shù)之類的。

而標準MFC DLL里面可以使用MFC,但是卻不能輸出。

非標準MFC DLL里面可以使用MFC,并且可以輸出。

下面是一個簡單的例子

頭文件

#pragma once

 

#ifdef DLLUSAGE_EXPORTS

     #define SIMPLE_API __declspec(dllexport)

#else

     #define SIMPLE_API __declspec(dllimport)

#endif

 

SIMPLE_API int AddTwoNumbers(int lhs, int rhs);

 

實現(xiàn)文件

SIMPLE_API int AddTwoNumbers(int lhs, int rhs)

{

Return lhs + rhs;

}

 

在生成 my.DLL 以后,再用

typedef int (*ADD)(int,int);

HINSTANCE instance = LoadLibrary("E:\\dllusage.dll");

if ( NULL == instance)

{

         MessageBox(NULL,"加載DLL錯誤",NULL,MB_OK);

         return 1;    

}

ADD myadd = (ADD)GetProcAddress(instance,TEXT("?AddTwoNumbers@@YAHHH@Z"));

if (NULL == myadd)

{

         MessageBox(NULL, "獲取函數(shù)地址錯誤",NULL,MB_OK);

         return 2;

}

int result = myadd(5, 6);

 

這里值得說明的一點是:

在第二個參數(shù)里面采用的是AddTwoNumbersDLL里面的名稱?AddTwoNumbers@@YAHHH@Z,相當于是DLL里面提供給我們調(diào)用的接口,如果不采用這樣的寫法,就會出現(xiàn)127錯誤

ERROR_PROC_NOT_FOUND

The specified procedure could not be found

因此我使用那種比較笨的辦法,用view denpends來查找到AddTwoNumbersDLL里面的入口地址,然后再去調(diào)用這個這個入口地址。

或者是采用這樣的方法:

Extern c

{

     SIMPLE_API int AddTwoNumbers(int lhs, int rhs);

}

這樣一來的好處就是:

ADD myadd = (ADD)GetProcAddress(instance,TEXT("AddTwoNumbers "));

你會發(fā)現(xiàn)這樣看起來要舒服一點,這個時候,你用view depends來查看DLL中該函數(shù)對應(yīng)的地址,就會發(fā)現(xiàn)變成了AddTwoNumbers

posted @ 2008-04-02 16:23 jolley 閱讀(338) | 評論 (1)編輯 收藏

// 摘自代碼大全2第九章
創(chuàng)建類和子程序的步驟概述.
1 開始
2 創(chuàng)建類的總體設(shè)計
3 創(chuàng)建類中的子程序
4 復(fù)查并測試整個類
5 完成
其中3與4之間要進行交互,這種交互主要是針對審查子程序進行的,并且2與3之間也要進行交互,這種交互主要針對子程序在類中的總體設(shè)計.
一個思想是:細化跟迭代,并且即使反饋直到類功能和子程序功能都清晰,再到5.
創(chuàng)建一個類的步驟
1)創(chuàng)建類的總體設(shè)計:
設(shè)計一個類的過程中包含一些特有的設(shè)計任務(wù)--定義類的特定職責,定義類所要隱藏的秘密,以及精確地定義類的接口所代表的抽象概念,決定這個類是否要從其他類派生而來,以及是否允許其它類再從它派生,指出這個類中關(guān)鍵的公用方法,標識并設(shè)計出類所需用到的重要數(shù)據(jù)成員.
2)創(chuàng)建類中的子程序
在前述第一個步驟中標識出類的主要子程序之后,還需要創(chuàng)建這些子程序.在編寫各個程序時通常還會引出更多的或重要,或次要的子程序,創(chuàng)建這些新加入的子程序的過程往往還會反過來波及類的總體設(shè)計
3)復(fù)審并測試整個類
通常情況下,子程序在創(chuàng)建的同時也經(jīng)過了測試,在整個類可以工作之后,應(yīng)該再對其整體進行復(fù)查和測試,以便發(fā)現(xiàn)那些在子程序的獨立測試層次上無法測出的問題.
在創(chuàng)建類的過程中,2),3)還是要求反復(fù)進行的,直到類的總體設(shè)計是最優(yōu)的.
創(chuàng)建子程序的步驟
創(chuàng)建子程序的過程中涉及到的主要活動: 設(shè)計子程序,檢查設(shè)計,編寫子程序的代碼,檢查代碼.
1 開始
2 設(shè)計子程序(主要借助于偽代碼)
3 檢查設(shè)計(主要是檢查偽代碼)
4 編寫子程序的代碼
5 復(fù)審并測試代碼
6 完成
其中2與3是要進行交互的,主要是保證偽代碼的質(zhì)量,4與5也是要進行交互的,這樣主要保證子程序的質(zhì)量.
偽代碼
偽代碼的指導(dǎo)原則:
1) 用類似英語的語句來精確描述特定的操作
2) 避免使用目標編程語言中的語法元素
3) 在本意的層面上編寫代碼,用偽代碼去描述解決問題的方法的意圖,而不是去寫如何在目標語言中實現(xiàn)這個方法.
4) 在一個足夠低的層次上編寫代碼,以便可以近乎自動地從它生成代碼.
通過偽代碼編程過程創(chuàng)建子程序
檢查先決條件
在動手去做子程序本身的任何工作之前,應(yīng)該先查看一下該子程序要做的工作是不是已經(jīng)定義好了,是不是能夠與整體設(shè)計相匹配.另外要結(jié)合項目的需求,檢查這個子程序是否真正必須的,至少是間接需要的.
定義子程序要解決的問題
陳述出該子程序?qū)⒁鉀Q的問題,敘述要足夠詳細,以便能去創(chuàng)建這個子程序,如果高層的設(shè)計已經(jīng)足夠詳細,那么這項工作可能已經(jīng)完成了,在這個高層的設(shè)計里至少應(yīng)該詳細說明下列信息.
1) 這一子程序?qū)⒁[藏的信息
2) 傳給這個子程序的各項輸入
3) 從該子程序得到的輸出
4) 在調(diào)用程序之前確保有關(guān)的前條件成立(輸入數(shù)據(jù)的取值位于特定范圍之中,有關(guān)的流已經(jīng)初始化,文件已經(jīng)打開或者關(guān)閉,緩沖區(qū)已經(jīng)填滿或者清空)
5) 在子程序?qū)⒖刂茩?quán)交回調(diào)用方程序之前,確保其后條件的成立(如輸出數(shù)據(jù)位于特定范圍之內(nèi),流已經(jīng)初始化,文件已經(jīng)打開或者關(guān)閉,緩沖區(qū)已填滿或清空)
其中4和5一般通過判斷前驅(qū)和后繼條件來進行的。前者是保證調(diào)用的條件是否成立,而后者是保證程序的返回值是否是合法的。
為子程序命名
一般地子程序已經(jīng)有一個清晰的,無二義性的名字,如果在命名這個子程序的名字的時候,有點困難,那么就說明,對該子程序的設(shè)計不是很清楚,而要去改善設(shè)計了。
決定如何測試子程序
在編寫一個子程序的時候,要想一想怎么才能測試它。這在以后的C/C++測試中都可以部署單元測試工具Xunit.
在標準庫中搜尋可用的功能
想用提高代碼的質(zhì)量和生產(chǎn)率,有一個最重要的途徑就是重用好的代碼。
考慮錯誤處理
考慮在子程序中可能出錯的環(huán)節(jié),子程序可以用多種方式來處理錯誤,應(yīng)該特別注意去選擇處理錯誤的方式。
考慮效率問題
主要是兩個方面的考慮,一是效率,而另一方面是性能。
研究算法和數(shù)據(jù)類型
如果在可用的程序庫里沒有所需的功能,它也許會在某本算法書中介紹過,決定從頭開始編寫一段復(fù)雜的代碼之前,查一下算法書看看有什么可用的內(nèi)容。如果采用一個已有明確定義的算法,則要保證這個算法正確地轉(zhuǎn)換為你所用的編程語言。
編寫偽代碼
前面的那些步驟主要是為確定一個思路,這在真正編寫程序的時候是很有幫助的,在完成前面的準備工作以后,就可以開始用高層次的偽代碼來寫程序。
一般是從寫子程序的注釋開始進行編制,主要是說明子程序的功能和目的。
考慮數(shù)據(jù)
在整個過程中的幾個不同環(huán)節(jié)對子程序所用的數(shù)據(jù)進行設(shè)計。
檢查偽代碼
在寫完偽代碼并設(shè)計完數(shù)據(jù)之后,花上幾分鐘時間復(fù)雜你寫的偽代碼,然后拋揩這些代碼,想想你該如何向別人解釋這些代碼。
在偽代碼中試驗一些想法,留下最好的想法
在你開始編寫代碼之前,應(yīng)盡可能用偽代碼去嘗試更多的想法。
編寫子程序的代碼
1 以偽代碼開始
2 寫出子程序的聲明
3 編寫第一條和最后一條語句,然后將偽代碼轉(zhuǎn)換為高層次的注釋。
4 每條注釋下面填充代碼
5 檢查代碼
6 收尾工作
7 完成
其中3,4,5可以按照需求進行重復(fù)。
寫出子程序的聲明
首先要寫出子程序的接口聲明,即C++中的函數(shù)聲明
把偽代碼轉(zhuǎn)變?yōu)楦邔哟蔚淖⑨?br>接下來,把第一條和最后一條語句寫出來,在C++中也就是"{"和"}".然后將偽代碼轉(zhuǎn)變成注釋.
在每條注釋下面填充代碼
在偽代碼注釋中的每一句話下面填寫代碼。
檢查代碼是否需要進一步分解
方法1:把這段注釋下面的代碼重構(gòu)(refactor)成一個新的子程序。
方法2:遞歸地應(yīng)用偽代碼編程過程。
檢查代碼
1) 在腦海里檢查程序中的錯誤。
理解每行代碼所起的作用,理解為什么需要這行代碼,沒有什么東西會僅僅因為它看上去可行就是正確的。
編譯子程序
完成檢查之后,就可以編譯這個程序了。
最大地發(fā)揮編譯子程序所產(chǎn)生的指導(dǎo)建議
1)把編譯器的警告級別調(diào)到最高,通過讓編譯器來檢測錯誤,你可以很容易地查出大量細微的錯誤。
2)使用驗證工具,可以通過使用類似lint這樣的工具來對C語言這類語言的編譯器所做的檢查結(jié)果進行補充檢查。
3)消除產(chǎn)生錯誤消息和警告的所有根源。
在調(diào)試器中逐步執(zhí)行代碼
程序編譯通過了之后,要在調(diào)試器中逐行執(zhí)行,以確保每行代碼都在按照你所期望的方式執(zhí)行。
測試代碼
使用你在開發(fā)該子程序期間計劃寫的或者已寫成的測試用例來測試代碼。你可能需要開發(fā)一些腳手架來支持你的測試用例
消除程序中的錯誤
一旦檢測到錯誤,就一定要把它除掉。
收尾工作
檢查子程序的接口
確定所有的輸入,輸出數(shù)據(jù)都參與了計算,并且所有的參數(shù)也都用到了。
檢查整體的設(shè)計質(zhì)量
檢查子程序中的變量
檢查子程序的語句和邏輯
檢查子程序的布局
檢查子程序的文檔
除去冗余的注釋。
小結(jié):
之前一直在寫程序,但是發(fā)現(xiàn)時不時思路很亂,也沒有有層次地,有系統(tǒng)地去思考這些類和子程序的設(shè)計,只是去實現(xiàn)一個功能,并且能夠達到所要的目的就可以了,后來發(fā)現(xiàn)經(jīng)常出問題,很常見的就是考慮不周全,在編制代碼以后,才開始反悔,后悔當初的設(shè)計,然后對程序產(chǎn)生了消極的情緒,讓我感覺不爽,看了代碼大全,發(fā)現(xiàn)提供了可行的方法.而且思路比以前清晰多了,感覺這個方法很有效,所以記錄在這里.


 

posted @ 2008-03-01 12:09 jolley 閱讀(1010) | 評論 (0)編輯 收藏

僅列出標題
共4頁: 1 2 3 4 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧洲在线一区| 欧美一区在线看| 欧美在线免费视频| 在线激情影院一区| 亚洲精品资源| 国产一区二区三区四区五区美女 | 99国产精品久久久久久久久久 | 欧美激情一区二区久久久| 欧美精品导航| 久久精品综合网| 欧美日韩国产在线播放网站| 久久成人精品| 欧美激情中文字幕乱码免费| 欧美精品v日韩精品v国产精品| 国产日韩精品一区二区浪潮av| 久久综合九色综合网站| 欧美日产一区二区三区在线观看 | 欧美精品一区二区在线播放| 久久国产精品一区二区| 欧美大色视频| 久久久久久久成人| 欧美色欧美亚洲另类二区| 久久人人爽人人爽| 欧美午夜片在线免费观看| 免费在线观看一区二区| 国产精品综合不卡av| 亚洲国产另类久久精品| 国产自产高清不卡| 中日韩美女免费视频网址在线观看| 亚洲激情视频在线播放| 欧美一区二区三区电影在线观看| 日韩写真在线| 免费观看成人鲁鲁鲁鲁鲁视频| 久久av二区| 国产精品免费一区二区三区在线观看| 亚洲高清成人| 亚洲国产精品v| 久久久精品欧美丰满| 欧美一区二区三区婷婷月色| 欧美涩涩视频| 日韩一级大片在线| 亚洲免费观看视频| 欧美大成色www永久网站婷| 久久亚洲精品一区二区| 国产一区欧美| 欧美一区二区三区免费观看| 亚洲欧美www| 国产精品福利在线观看| 99国产精品视频免费观看| 一区二区欧美在线| 欧美另类在线播放| 亚洲国产精品欧美一二99| 136国产福利精品导航| 久久久久高清| 美女成人午夜| 在线日韩精品视频| 久久亚洲欧美| 欧美二区在线观看| 亚洲欧美日韩区| 欧美成人在线影院| 亚洲国产片色| 欧美成人免费全部观看天天性色| 久久久久免费观看| 国内不卡一区二区三区| 久久久www| 蜜桃久久av一区| 一区二区在线视频观看| 狼人社综合社区| 亚洲国产精品一区在线观看不卡 | 日韩亚洲不卡在线| 亚洲男人的天堂在线| 国产精品久久久久久影院8一贰佰 国产精品久久久久久影视 | 新67194成人永久网站| 欧美在线一二三区| 狠狠色丁香久久综合频道| 久久九九免费视频| 亚洲国产高清一区| 亚洲欧美区自拍先锋| 国产日韩一区在线| 久久午夜色播影院免费高清| 亚洲高清视频在线| 亚洲视频网站在线观看| 国产精品久久久一本精品| 欧美亚洲综合在线| 亚洲电影毛片| 在线亚洲美日韩| 国产精品亚洲网站| 久久夜色精品| 一区二区三区日韩精品视频| 性色av一区二区三区| 在线成人国产| 欧美日韩精品一区二区三区四区 | 伊人久久大香线蕉av超碰演员| 蜜臀av性久久久久蜜臀aⅴ| 亚洲欧洲一区二区在线观看| 香蕉免费一区二区三区在线观看| 狠狠色丁香久久婷婷综合_中| 欧美激情综合五月色丁香| 亚洲永久免费| 亚洲国产精品t66y| 亚洲欧美在线观看| 亚洲国产欧美不卡在线观看 | 亚洲免费精品| 久久精品视频在线看| 日韩亚洲欧美在线观看| 国内外成人免费视频 | 欧美成人一区二区三区| 亚洲午夜视频在线| 136国产福利精品导航网址| 欧美亚洲第一区| 久热国产精品视频| 亚洲一区二区三区色| 亚洲国产成人av| 久久精品日产第一区二区三区 | 老色批av在线精品| 亚洲图片欧美日产| 亚洲国产一区二区视频| 久久岛国电影| 亚洲欧美日韩精品久久久| 亚洲激情视频在线| 极品少妇一区二区三区| 国产精品美女在线观看| 欧美高清在线| 久久一二三国产| 久久9热精品视频| 亚洲欧美视频在线| 久久久午夜视频| 男女激情久久| 亚洲国产精品va在线观看黑人 | 蜜桃av一区二区| 亚洲社区在线观看| 亚洲国产欧美一区二区三区同亚洲 | 欧美激情视频免费观看| 久久国内精品自在自线400部| 一区二区高清视频| 亚洲黄色在线观看| 尤物九九久久国产精品的特点| 国产欧美精品一区aⅴ影院| 欧美午夜精品理论片a级大开眼界| 欧美激情一区二区三区蜜桃视频| 亚洲国产美女| 欧美激情亚洲另类| 欧美激情偷拍| 欧美国产精品v| 久久亚洲私人国产精品va媚药| 性欧美8khd高清极品| 亚洲欧美日韩区| 香蕉国产精品偷在线观看不卡| 亚洲视频国产视频| 亚洲美女性视频| 亚洲日本欧美日韩高观看| 国语自产精品视频在线看抢先版结局 | 激情另类综合| 国产一区二区三区久久悠悠色av| 久久免费高清视频| 久久综合一区| 蜜桃伊人久久| 亚洲一区二区三区涩| 亚洲国产cao| 99www免费人成精品| 亚洲天堂免费观看| 亚洲精品美女在线观看| 在线亚洲精品福利网址导航| 美日韩精品视频| 欧美一区二区观看视频| 亚洲国产高潮在线观看| 国产精品男人爽免费视频1| 久久久久国产精品麻豆ai换脸| 久久婷婷av| 欧美精品精品一区| 欧美mv日韩mv国产网站| 欧美日韩国产999| 性欧美xxxx大乳国产app| 男人的天堂亚洲在线| 亚洲三级免费| 亚洲综合第一页| 久久久精品一区| 亚洲人精品午夜| 午夜精品免费视频| 另类av一区二区| 欧美精品一区在线观看| 国产精品一区在线观看你懂的| 黄色成人免费观看| 一本色道久久88精品综合| 欧美一区免费| 亚洲缚视频在线观看| 亚洲性av在线| 欧美a一区二区| 国产日韩欧美一区| 99天天综合性| 久久一区二区三区国产精品| 欧美1区2区视频| 在线一区二区三区做爰视频网站| 久久精品道一区二区三区| 欧美日韩亚洲一区在线观看| 好吊色欧美一区二区三区四区| 在线午夜精品| 亚洲国产精品第一区二区三区| 欧美一区二区高清| 欧美视频亚洲视频|