节数作为后缀,因此当我们通过GetProcAddress传入函数名获取函数指针时,由于名称不匹配,所以返回的函数指针将为NULL。和stdcall不同的是,基于cdcel调用规范生成的导出函数不存在这样的问题。我们可以通过Windows提供的Dependency工具予以证明。
2. 定义一个实现类继承自上面定义的纯虚接口,该类将包含大量和libmemcached相关的细节信息,同时也需要在该类中include和libmemcached相关的头文件,而不是再自行重新定义和libmemcached相关的细节信息,最后再通过动态加载的方式进行加载,见如下代码声明:
1 #include
2 #include
3
4 class MemcachedClientWrapperImpl : public MemcachedClientWrapper
5 {
6 public:
7 MemcachedClientWrapperImpl();
8 virtual ~MemcachedClientWrapperImpl();
9
10 public:
11 virtual bool initialize(bool consistentHash = false, bool supportCAS = false);
12 void release();
13 int addServer(const char* serverIP, const int port);
14 bool set(void* key,int klength,void* data,int dlength);
15 bool add(void* key,int klength,void* data,int dlength);
16 bool replace(void* key,int klength,void* data,int dlength);
17 bool append(void* key,int klength,void* data,int dlength);
18 bool get(void* key,int klength,MCFetchedData*& fetchedData);
19 bool gets(void** keys,int* keysLength,int count);
20 bool fetchNext(MCFetchedData*& fetchedData,bool* isEof = 0);
21 bool remove(void* key,int klength);
22 bool exists(void* key,int klength,bool* ok = NULL);
23 bool updateWithCAS(void* key,int klength,void* data,int dlength);
24 bool updateWithAtomicIncrement(void* key,int klength,int step,uint64& value,int* defaultValue = 0);
25 bool updateWithAtomicDecrement(void* key,int klength,int step,uint64& value,int* defaultValue = 0);
26 bool clean();
27
28 private:
29 memcached_st* _mc;
30 memcached_return _mr;
31 uint64_t _cas;
32 bool _initialized;
33 bool _supportCAS;
34 };
3. 还是在Mingw32环境下,编写makefile文件,生成新的动态库,该库将依赖libmemcached库。见如下makefile:
all:
g++ -I/usr/local/include -I"/home/Administrator/MemcachedClientWrapper" ../MemcachedClientWrapperImpl.cpp -o ./MemcachedClientWrapperImpl.o -O3 -w -c -fmessage-length=0 -MMD -MP -MF"MemcachedClientWrapperImpl.d" -MT"MemcachedClientWrapperImpl.d"
g++ -L/usr/local/bin -shared -o "./MemcachedClientWrapper.dll" ./MemcachedClientWrapperImpl.o -lmemcached-8
见以下说明:
1) MemcachedClientWrapperImpl.cpp文件中包含接口的实现部分已经两个导出C函数的实现。
2) /usr/local/include: 中包含libmemcached的相关头文件,是在libmemcached的make install中copy过去的。
3) /home/Administrator/MemcachedClientWrapper: 该目录包含该Wrapper工程头文件所在目录。
4) /usr/local/bin: 该目录包含libmemcached生成的dll文件。
5) libmemcached-8.dll: 当前版本libmemcached生成的动态库。
6) MemcachedClientWrapper.dll: 为最终生成的动态库。
4. 在执行完步骤3之后,我们将得到两个dll,一个是原有的libmemcached.dll,另一个则为我们封装后的MemcacheClientWrapper.dll。在此之后,我们的VC程序将只是面对封装后的动态库及其导出接口,而libmemcached中的导出信息已经被很好的封装在Wrapper的内部了。我们现在需要做的便是在我们的工程中将纯虚接口所在的头文件包含进我们的工程中,然后在定义两个C函数指针,其函数签名和Wrapper中导出的两个C函数保持一致,见如下代码:
typedef MemcachedClientWrapper* (*createWrapper)();
typedef void (*releaseWrapper)(MemcachedClientWrapper*);
5. 最后我们需要做的是在我们的测试用例中利用该Wrapper导出的纯虚接口来操作libmemcached,以便和Memcached服务器进行通讯和数据存储,见如下用例代码:
1 #include
2
3 int main()
4 {
5 MemcachedClientWrapper* wrapper = createMCWrapper();
6 void* key = malloc(20);
7 void* data = malloc(20);
8 memcpy(key,"helloworld",10);
9 memcpy(data,"i love you, my baby.",20);
10