• <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>

            concentrate on c/c++ related technology

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

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

            常用鏈接

            留言簿(9)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            #

            我在MSVC6里的win32 console工程里面寫(xiě)了一段這樣的代碼,已經(jīng)去掉了不必要的代碼已達(dá)到注意重點(diǎn)地目點(diǎn):
            #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() );
                }
            編譯以后,得到以下兩個(gè)錯(cuò)誤:

            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)頭文件。卻在編譯的時(shí)候出現(xiàn)兩個(gè)錯(cuò)誤。

            問(wè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)里面的版本過(guò)低,導(dǎo)致出現(xiàn)無(wú)法進(jìn)入上述條件編譯里面,因此需要做的事情是,要么將條件編譯注釋掉,其實(shí)問(wèn)題也不大,反正以后也不會(huì)有什么變動(dòng),要么就是在stdafx.h最前面重新定義一個(gè)_WIN32_WINNT,并且這個(gè)定義值應(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 閱讀(723) | 評(píng)論 (0)編輯 收藏

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

            給 ATL EXE 項(xiàng)目添加 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. 更改項(xiàng)目設(shè)置以使用 MFC。 在 Project Settings 對(duì)話框中,單擊 General 選項(xiàng)卡,然后將 Microsoft Foundation Classes 列表框中的設(shè)置更改為 MFC。
            3. 添加 CWinApp 衍生類(lèi),并聲明一個(gè)該類(lèi)型的全局變量,如下所示:
            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. 對(duì)于 Unicode 版本,請(qǐng)確保進(jìn)入點(diǎn)被設(shè)置為 wWinMainCRTStartup,該設(shè)置在 Project Settings 對(duì)話框中 Link 字段的 Output 類(lèi)別中。 有關(guān)其它信息,請(qǐng)參見(jiàn) Microsoft Knowledge Base 中的下列文章:
            125750 (http://support.microsoft.com/kb/125750/EN-US/) PRB: 錯(cuò)誤 LNK2001: “_WinMain@16”: 不能解析的外部符號(hào)
            6. 將以下代碼行添加到 COM 接口、窗口過(guò)程和導(dǎo)出函數(shù)的每個(gè)成員函數(shù)的開(kāi)頭:
            AFX_MANAGE_STATE(AfxGetAppModuleState());
            有關(guān) AFX_MANAGE_STATE 的詳細(xì)信息,請(qǐng)查詢 VC++ 聯(lián)機(jī)文檔。
            有關(guān)將 MFC 支持添加到 ATL COM AppWizard 項(xiàng)目的詳細(xì)信息,請(qǐng)參見(jiàn)下面的 Microsoft Knowledge Base 文章:

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

            回到頂端

            將 MFC 支持添加到 ATL DLL 項(xiàng)目



            執(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 接口、窗口過(guò)程和導(dǎo)出函數(shù)的每個(gè)成員函數(shù)的開(kāi)頭:
            AFX_MANAGE_STATE(AfxGetStaticModuleState());
            有關(guān)其它信息,請(qǐng)參見(jiàn) Microsoft Knowledge Base 中的下列文章:
            140850 (http://support.microsoft.com/kb/140850/EN-US/) HOWTO: 轉(zhuǎn)換 DLLTRACE 以使用共享庫(kù)中的 MFC

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

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

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

            3)
            之前認(rèn)為共享內(nèi)存嘛,應(yīng)該是可以共享任何對(duì)象的,但是我在共享一個(gè)deque的時(shí)候,發(fā)現(xiàn)錯(cuò)了,后來(lái)才發(fā)現(xiàn)文件映射不能共享指針的,deque是STL的一個(gè)序列式容器,而其內(nèi)部都是一系列的指針組成的,后來(lá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.
            可以共享的是非指針的用戶自定義類(lèi)型, 以及內(nèi)建類(lèi)型等,不包括含有指針的各種類(lèi)型。


               


             

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

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

            這回貼上來(lái)自codeguru上面的一篇討論,感覺(jué)很舒服:
               

            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 閱讀(477) | 評(píng)論 (0)編輯 收藏

             

            今天第一次寫(xiě)DLL

            DLL里面有三種類(lèi)型,win32 DLL, 標(biāo)準(zhǔn)MFC DLL,以及非標(biāo)準(zhǔn)MFC DLL

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

            而標(biāo)準(zhǔn)MFC DLL里面可以使用MFC,但是卻不能輸出。

            非標(biāo)準(zhǔn)MFC DLL里面可以使用MFC,并且可以輸出。

            下面是一個(gè)簡(jiǎn)單的例子

            頭文件

            #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);

             

            實(shí)現(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錯(cuò)誤",NULL,MB_OK);

                     return 1;    

            }

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

            if (NULL == myadd)

            {

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

                     return 2;

            }

            int result = myadd(5, 6);

             

            這里值得說(shuō)明的一點(diǎn)是:

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

            ERROR_PROC_NOT_FOUND

            The specified procedure could not be found

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

            或者是采用這樣的方法:

            Extern c

            {

                 SIMPLE_API int AddTwoNumbers(int lhs, int rhs);

            }

            這樣一來(lái)的好處就是:

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

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

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

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


             

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

            僅列出標(biāo)題
            共4頁(yè): 1 2 3 4 
            久久久久久毛片免费看| 青青草原综合久久| 久久久久国色AV免费看图片| 精品少妇人妻av无码久久| 久久精品国产亚洲AV香蕉| 久久国产精品无码网站| 狠狠精品干练久久久无码中文字幕| www.久久热.com| 精品国产一区二区三区久久| 久久99精品久久只有精品| 亚洲精品高清国产一线久久| 7777精品伊人久久久大香线蕉| 欧美成人免费观看久久| 国产精品久久久久久久app| 久久国产精品无| 久久久久亚洲AV成人网人人网站 | 97精品依人久久久大香线蕉97| 久久久精品国产Sm最大网站| 人妻少妇精品久久| 国产精品99久久久精品无码| 性做久久久久久久| 久久99精品久久久久久久久久| 99久久精品费精品国产一区二区| 99精品久久久久中文字幕| 国产成人香蕉久久久久| 人妻丰满?V无码久久不卡| 亚洲中文久久精品无码ww16 | 亚洲一区二区三区日本久久九| 蜜桃麻豆www久久| 香蕉久久夜色精品国产尤物| 亚洲精品乱码久久久久久蜜桃图片 | 国产综合久久久久久鬼色| 国产精品久久毛片完整版| 久久国产免费| 77777亚洲午夜久久多人| 久久精品嫩草影院| 亚洲va久久久久| 一本一道久久精品综合| 一本一道久久a久久精品综合 | 久久亚洲精品成人无码网站 | 久久国产一片免费观看|