用Delphi 编写DLL的时候,如果要给其它语言编写的程序或DLL来使用的话,一般最好使用与Windows API兼容的数据类型来作为输出函数的参数和返回值,这样可以保证做出来的DLL可以被大多数主流的开发工具来调用。比如一个处理字符串的函数,就不要使用Delphi 自己的string类型来表示字符串数据,而应该使用通用的PChar类型来表示。
如果DLL里面的输出函数涉及到PChar这样的动态数据的话,最好不要把内存分配和释放的代码分别放到不同的模块中。如果你经常使用Windows API函数的话,就可以发现,当函数使用缓冲区来返回一个结果的时候,都是要求调用者程序自己分配和释放缓冲区所需的存储空间,而函数只负责将数据填充到缓冲区中。那么我们写DLL的时候,也可以借鉴这种原则:函数使用PChar来接收和返回要处理的字符串数据(由于PChar本身是指针,所以PChar类型的参数不用定义为变参也可以用于返回处理结果),而函数的返回值则可以用来表示实际被处理的数据量大小(如果调用函数时传递的指针是空的,还可以用返回值表示缓冲区所需的内存大小,调用者根据这个大小来自己分配内存)。应用这种模式来进行DLL编程的好处在于,内存分配和释放都是在调用者程序中处理的,这样即使发生非法指针操作也可以确定是调用者本身的问题,与DLL里面的函数无关,DLL只需负责数据处理,不应该插手内存管理的问题。真正的DLL内存共享应该通过内存映射文件进行,而不是函数参数和全局变量等手段。
ShareMem是什么东西?什么时候需要使用ShareMem?简单的说,ShareMem就是Delphi的Windows 程序共享内存管理器动态链接库--BORLANDMM.DLL--的编程接口单元。它的作用是:如果一个用Delphi编写的DLL函数使用了AnsiString或动态数组来作为参数或返回值的数据类型的话,那么就必须在DLL的源程序和调用者源程序里面都加上ShareMem这个单元。另外还有一种情况也必须使用ShareMem单元,就是动态分配的内存的分配和释放的动作不是在同一个模块中进行的时候,比如在DLL里面分配内存,在调用者程序里面释放。由此可以看出,这个BORLANDMM.DLL主要是为Delphi写的各程序模块间共享内存时使用的,对于其他语言编写的程序而言它没什么作用。对于使用PChar类型来表示和处理字符串数据的DLL来说,即使DLL源程序和调用者源程序都是用Delphi编写的,如果能遵循上述的编程原则--即DLL负责数据处理--动态分配和释放的内存空间由调用者程序自己负责和管理,也就没有必要使用ShareMem单元了。