在VS2008下用ACE创建及使用DLL(动态链接库)
下面是 ACE-6.0.0 提供的创建及使用DLL的实例,代码所在目录:\ACE-6.0.0\ACE_wrappers\examples\Export 。
DLL的代码:
1. dll.h 文件
// $Id: dll.h 80826 2008-03-04 14:51:23Z wotte $ // To use the export macros with a DLL, a file will need to be // created (see ACE_wrapper/bin/generate_export_file.pl) and // included. This file defines Test_Export (and the // TEST_SINGLETON_* macros). #include "test_export.h" #include "ace/Singleton.h" #include "ace/Null_Mutex.h" #define RETVAL 42 // To expose a function outside of a DLL, use the *_Export // at the beginning of the function declaration. Test_Export int test_function (); // To expose data, put use the *Export at the beginning // of the variable declaration. The extern is required when // building static libraries. extern Test_Export int test_variable; // To expose a class, put the *_Export between "class" // and the class name. class Test_Export test_class { public: int method (); }; // ACE_Singleton and its relatives are special cases. The problem is // that ACE_Singleton is a template. If the singleton is used in both // the DLL and the executable linking the DLL, then two instances of // the singleton will be used (which defeats the purpose of a Singleton). // // This occurs because the ACE_Singleton template is expanded in both // places because Visual C++ and Borland C++ do this automatically by // including the template source. This in turn creates two copies of // the static member variable. // // So to get around this problem, the *_SINGLETON_DECLARE macro is // used to instruct the compiler to not create the second copy in the // program. This macro solution does not work for Borland C++, so for // this compiler you must explicitly disable the template instantiation // using a #pragma (or use the other workaround below). // // Another workaround for this is to not to expose the Singleton itself // to the outside world, but to instead supply a function or static // member function that returns the singleton to the executable // (like get_dll_singleton () does below). #if defined (__BORLANDC__) # if !defined (TEST_BUILD_DLL) # pragma option push -Jgx # endif #endif TEST_SINGLETON_DECLARE (ACE_Singleton, test_class, ACE_Null_Mutex) #if defined (__BORLANDC__) # if !defined (TEST_BUILD_DLL) # pragma option pop # endif #endif typedef ACE_Singleton<test_class, ACE_Null_Mutex> TEST_SINGLETON; Test_Export test_class *get_dll_singleton ();
2. dll.cpp 文件
// $Id: dll.cpp 80826 2008-03-04 14:51:23Z wotte $ #include "dll.h" int test_variable = 0; int test_function () { test_variable = RETVAL; return RETVAL; } int test_class::method () { return RETVAL; } test_class * get_dll_singleton () { return TEST_SINGLETON::instance (); } #if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION) template ACE_Singleton<test_class, ACE_Null_Mutex> *ACE_Singleton<test_class, ACE_Null_Mutex>::singleton_; #endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
测试上面DLL的代码:
1. test_export.h 文件
// -*- C++ -*- // $Id: test_export.h 80826 2008-03-04 14:51:23Z wotte $ // Definition for Win32 Export directives. // This file is generated automatically by // generate_export_file.pl // ------------------------------ #if !defined (TEST_EXPORT_H) #define TEST_EXPORT_H #include "ace/config-all.h" #if defined (ACE_AS_STATIC_LIBS) && !defined (TEST_HAS_DLL) # define TEST_HAS_DLL 0 #endif /* ACE_AS_STATIC_LIBS && ! TEST_HAS_DLL */ #if !defined (TEST_HAS_DLL) #define TEST_HAS_DLL 1 #endif /* ! TEST_HAS_DLL */ #if defined (TEST_HAS_DLL) # if (TEST_HAS_DLL == 1) # if defined (TEST_BUILD_DLL) # define Test_Export ACE_Proper_Export_Flag # define TEST_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) # define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) # else # define Test_Export ACE_Proper_Import_Flag # define TEST_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) # define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) # endif /* TEST_BUILD_DLL */ # else # define Test_Export # define TEST_SINGLETON_DECLARATION(T) # define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) # endif /* ! TEST_HAS_DLL == 1 */ #else # define Test_Export # define TEST_SINGLETON_DECLARATION(T) # define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) #endif /* TEST_HAS_DLL */ #endif /* TEST_EXPORT_H */ // End of auto generated file.
2. test.cpp 文件
// $Id: test.cpp 80826 2008-03-04 14:51:23Z wotte $ #include "dll.h" #include <ace/streams.h> int ACE_TMAIN (int, ACE_TCHAR *[]) { int failure_count = 0; test_class my_test_class; // Tet out the export of a class. I don't see // How this can fail at runtime (rather it would // probably give link errors), but just in case... cout << "Method Test: "; if (my_test_class.method () != RETVAL) { cout << "Failed" << endl; ++failure_count; } else cout << "Succeeded" << endl; // Test out the export of a function. Like above, // I don't know how this can fail at runtime. cout << "Function Test: "; if (test_function () != RETVAL) { cout << "Failed" << endl; ++failure_count; } else cout << "Succeeded" << endl; // Also test out the export of data. cout << "Variable Test: "; if (test_variable != RETVAL) { cout << "Failed" << endl; ++failure_count; } else cout << "Succeeded" << endl; // Test out the ACE_Singleton export by checking to see // that we have the same instance pointer as the DLL does. // This can fail at runtime. cout << "Singleton Test: "; if (TEST_SINGLETON::instance () != get_dll_singleton ()) { cout << "Failed" << endl; ++failure_count; } else cout << "Succeeded" << endl; getchar(); // Return the number of failures return failure_count; }