Error

C++博客 首页 新随笔 联系 聚合 管理
  217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks

#

    今天很偶然的在cppblog上看了个博客,提到这个API,然后我想起来之前很困惑的一个问题。为什么别人的程序.exe和.dll是放在不同目录的,而我的不能。起初我想的是也许只能用添加path这一招了。今天偶然看到这个函数顺便msdn一下发现还是挺有用的。以后俺们的dll和exe也不用恶心的都丢到一起了,可以根据模块和功能放到不同的目录了。

   

 

SetDllDirectory function

9 out of 18 rated this helpful - Rate this topic

Applies to: desktop apps only

Adds a directory to the search path used to locate DLLs for the application.

Syntax

C++

BOOL WINAPI SetDllDirectory(
  __in_opt  LPCTSTR lpPathName
);

Parameters
lpPathName [in, optional]

The directory to be added to the search path. If this parameter is an empty string (""), the call removes the current directory from the default DLL search order. If this parameter is NULL, the function restores the default search order.

Return value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

Remarks

The SetDllDirectory function affects all subsequent calls to the LoadLibrary and LoadLibraryEx functions. It also effectively disables safe DLL search mode while the specified directory is in the search path.

After calling SetDllDirectory, the standard DLL search path is:

  1. The directory from which the application loaded.
  2. The directory specified by the lpPathName parameter.
  3. The system directory. Use the GetSystemDirectory function to get the path of this directory. The name of this directory is System32.
  4. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
  5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  6. The directories that are listed in the PATH environment variable.

Each time the SetDllDirectory function is called, it replaces the directory specified in the previous SetDllDirectory call. To specify more than one directory, use theAddDllDirectory function and call LoadLibraryEx with LOAD_LIBRARY_SEARCH_USER_DIRS.

To revert to the standard search path used by LoadLibrary and LoadLibraryEx, call SetDllDirectory with NULL. This also restores safe DLL search mode based on theSafeDllSearchMode registry value.

To compile an application that uses this function, define _WIN32_WINNT as 0x0502 or later. For more information, see Using the Windows Headers.

posted @ 2012-06-27 22:58 Enic 阅读(321) | 评论 (0)编辑 收藏

boost::implicit_cast

在stackoverflow上看到这个帖子, 于是发现了boost::implicit_cast这个小东西.

先来看看这段代码:

struct top {};
struct mid_a : top {};
struct mid_b : top {};
struct bottom : mid_a, mid_b {};

void foo(mid_a&) {}
void foo(mid_b&) {}
void bar(bottom &arg) {
    foo(arg); // 想要调用"void foo(mid_a&)"
}

int main() {
    bottom x;
    bar(x);
    return 0;
}

是无法编译通过的, 因为foo的重载解析有歧义. 那么把bar里的代码改一改, 为了保持C++风格, 我们使用static_cast, 而不是C风格的转换:

foo(static_cast<mid_a&>(arg));

程序编译通过了, 运行起来也没有问题, 然而…

一个月以后我把bar的参数类型修改了一下:

struct top {};
struct mid_a : top {};
struct mid_b : top {};
struct bottom : mid_a, mid_b {};

void foo(mid_a&) {}
void foo(mid_b&) {}
void bar(top &arg) {
    // ... 过了一个月, 这里已经添加了很多代码.
    foo(static_cast<mid_a&>(arg));
}

int main() {
    top x;
    bar(x);
    return 0;
}

代码依旧编译通过, 可是运行时程序挂掉了(假设这几个类里面有许多成员, 并且在foo里对其进行了访问).

发现问题了吗? 原因就在于static_cast太强大了, 强大到可以进行”down-cast”. 于是编译器没有给你任何警告, 就把一个top类型的引用给强制转换成了min_a的引用.

这个时候轮到boost::implicit_cast出场了. 把bar里面的那句foo调用改一改:

foo(boost::implicit_cast<mid_a&>(arg));

于是一个月前的代码依旧可以通过编译, 而一个月后的代码中的错误被编译器揪出来了. 原因在于隐式类型转换不允许”down-cast”, 只能”up-cast”.

这里简要说一下所谓显式和隐式类型转换的区别. 在C++世界的英文里, 我们说”convert”通常指”implicit convert”, 而”cast”指”explicit cast”. 隐式类型转换好理解, 就是你写了个a=b, 而ab不同类型, 编译又不报错, 就说明隐式类型转换发生了, 类似的情况还有在函数调用的参数传递时. 而显式类型转换特指C风格的强制转换((type)obj或者C++中等价的type(obj)), 以及C++风格的四个关键字(static_cast, const_cast, dynamic_cast, reinterpret_cast). 然而这个定义是相当模糊的, 比如一个int类型的x, bool(x)是显式的, 而!!x是隐式的, 其实效果上并没有区别, 只是字面上的不同罢了. (关于cast和convert的区别, 参见这里这里)

所以在bar里我们需要的仅仅是一个隐式类型转换, 然而直接把arg传递给foo的话会出现重载歧义, 于是我们需要告诉编译器到底要进行哪个隐式类型转换. 然而static_cast又太过强大, 它还能做隐式类型转换之外的事情(up-cast), 于是在日后代码演化的过程中留下了bug.

于是boost::implicit_cast应运而生, 它比static_cast弱, 正如它的名字一样, 它只能用来告诉编译器执行什么隐式类型转换.

而它的代码呢? 简单到令人发指:

template <typename T>
inline T implicit_cast (typename mpl::identity<T>::type x) {
    return x;
}

而mpl::identity的定义也极其简单:

template<typename T> struct identity { typedef T type; };

有人要问这个identity干什么用的, 看起来很累赘. 如果没有这个identity, 像”implicit_cast(obj)”这样的代码也能通过编译, 然而它其实什么也没做, obj的类型仍然没变. identity的存在使得函数模板的参数类型推导失效, 因为要推导出T, 首先得知道identity是什么, 而identity又是依赖于T的. 于是就形成了循环依赖, 参数类型推导就失效了. 于是编译器就要求你显式地指定T的类型.

posted @ 2012-06-23 21:34 Enic 阅读(1641) | 评论 (1)编辑 收藏

    老早就想做这个事情了,想当初做协议代码实现的时候那个揪心啊,各种重复的代码一遍一遍的写。后来发现了Google的Protobuf,初次看见真TMD惊艳,,,

    吐槽下,Google的开源项目都不怎么地道,基本都是开代码不开文档,或文档少的可怜,,,

    在后来项目上要用到序列化技术,而且我们的序列化工具类是键值对。何为键值对呢,,,囧,这个很难描述,先暂时记录下我对序列化的理解。

 

//////////////////////////////////////////////////////////////////////////////////////////////

序列化一个抽象的概念,每个人可能理解都不同,我们约定这里谈的序列是这个:

    序列化就是把一个语言成面上的依赖上下文的“对象”,变成一个精炼的语言、上下文无关的数据(可以是一块内存,可以是一坨文件等等任何数据的载体)的动作;

抽空百度了下,百度百科给出的解释如下:

序列化 (serialization) 将对象的状态信息转换为可以存储或传输的形式的过程。

//////////////////////////////////////////////////////////////////////////////////////////////

 

题外话结束,继续说我们项目上需求的键值对。

刚刚的穿插序列化定义理解中可以分析出:一个序列化的数据中除了包含有原始的“数据”信息应该还包含有“数据”的描述信息。一般的需求中这个描述信息只要包含有类型信息就好了。

    比如某个“对象”序列化以后数据信息是0x63,我去,,,鬼才能知道这是什么意思,是数字?字符?还是什么别的特殊的东西?

    所以需要描述信息。比如1表示是字符,2表示是int,3表示是系统内部特定标识等等,,,

    这个偶们的键值对还是没有任何关系? no no no,我们的键值对就是除了这个类型信息呢,还要加一个名字。偶们内部的变量不仅是有类型的还是有名字的,,,也就是说描述信息中除了有类型还要有名字,,,

 

////////////////////////////////////////////////////////////////////////////////////////////

前几天研究了下浮点怎么在网络中传输。应为不同的机器或者不同的OS对浮点存储方式是不同的。后来研究了下几个开源的项目加上自己突然想起来大端小端int在网络上的传输方式,突然发现这个问题没有纠结的价值。标准嘛,大家统一标准就好了,谁的影响力大咱们就听谁的,,,要拥抱世界,尽量成为一个兼容的标准。无法反抗,那就只能享受了吧,,,谁让人家拳头大,推广好呢?

///////////////////////////////////////////////////////////////////////////////////////////

 

恩?刚刚上面不是主题,主题是这半个月要在不影响工作的前提下好好研究代码生成技术,其实这是为后面咱自己的序列化工具(类Google protobuf)打基础哈,,,

叫啥名好呢?囧,,,但愿这次咱能坚持做出来,,,

posted @ 2012-06-23 21:01 Enic 阅读(219) | 评论 (0)编辑 收藏

image

据说以前是支持的,现在是?

怕大伙都用工具搬家搬走了去了?

 

抱怨下,,,别无它意,,,囧啊,,,

posted @ 2012-06-23 00:38 Enic 阅读(91) | 评论 (0)编辑 收藏

不在乎系统有多乱,而在乎能向前演进,弃糟粕,留精华。,,,
posted @ 2011-09-29 00:28 Enic 阅读(84) | 评论 (0)编辑 收藏

这半年多时间陷入码海,整天晕头转向,发现还是不行,每一套代码都是不同的思想,而我总是追求完美,每套代码都挑剔出各种毛病,,,

其实回头看来,是方向错了,我不是要研究别人做了什么,而是我要做什么然后去看看别人怎么做的,,,

真相再次,,,任何东西都不能脱离了需求,,,
posted @ 2011-07-06 18:17 Enic 阅读(138) | 评论 (0)编辑 收藏

/*

    有两个数组a,b,大小都为n,数组元素的值任意整形数,无序;
    要求:通过交换a,b中的元素,使[数组a元素的和]与[数组b元素的和]之间的差最小。

*/

posted @ 2011-05-12 09:56 Enic 阅读(673) | 评论 (0)编辑 收藏

仅列出标题
共22页: First 14 15 16 17 18 19 20 21 22