回 帖 发 新 帖 刷新版面

主题:菜鸟求助:书上编DLL的讲解我看不懂啊!



我设计了一个用c++builder 6(已汉化) 编的对50Hz进行滤波的exe滤波器,公司要求将其改编为dll文件,并加在一个呈现波形的主程序(exe)前面,另外,该DLL文件,应具有检测其本身滤波特性的功能。

过去,我从来没编过DLL文件,一窍不通。看一本书:科学出版社《c++builder 6 程序设计教程》上面的介绍,越看越迷糊,而且书上对DLL的介绍只有二、三页,没有讲透。在此求助。

1、书上说:双击c++builder 6,打开后,按“文件-新建-其他-dll wizard”,就生成一个dll文件。
但我按全部保存,生成的是cpp和bpr,和新建窗体时生成的文件,后缀名完全相同。哪有什么DLL文件啊?

2、在编辑时,我输入的是书上的范例,如下:

double dblValue(double);
double halfvalue(double);
extern "C" __declspec(dllexport) double __stdcall changeValue
(double,bool);

double dblValue(double value)
{
  return value*value;
}

double halfValue(double value)
{
  return value/2.0;
}

__declspec(dllexport) double __stdcall changevalue(double value,bool which)
{
  return which?dblValue(value):halfValue(value);
}




int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
        return 1;
}
//---------------------------------------------------------------------------

奇怪的是,上面第三句,在我编辑到extern "C" __declspec时,
然后继续照书上抄,却显示错误信息,如下:
[C++ Error] Unit1.cpp(1): Unable to invoke Code Parameters due to errors in source code

这是怎么回事?照书上抄,都出错,这太打击我的积极性了!

3、公司里的程序员告诉我,本公司程序员多采用“隐式调用法”。保存程序时,不应该选“全部保存”,而应该选“工程-生成project2”,但这样一来,我又不明白了:
一则,书上根本没有提到这种保存方法,二则,书上还说用implib生成LIB文件,但这种“工程-生成project2”的方法,固然令我高兴地看到,总算生成DLL文件了,但也生成了我不希望生成的LIB文件,这样一来,还用implib命令干什么呢?

再问个菜鸟问题:用implib命令之前,必须已经生成了DLL文件,对不对?

4、这种所谓“编一个DLL文件”,实际上,到底生成了几个文件,是不是三个:DLL、LIB、调用该DLL的某个程序。

5、请问:为什么要生成LIB文件?我需要生成它吗?

6、这些文件,到底应该放在什么位置?如果乱放的话,难道调用程序就能在整张硬盘上搜索,从而找到它吗?
比如,我将DLL、LIB等文件放在“C:\Documents and Settings\Administrator”文件夹下面,将调用它(我也不知这个“它”,到底是
DLL还是别的什么)的CPP程序,放在“E:\BC\Dll学习”文件夹下面,如何?然后点击“运行”,就生成了exe,对不对?

回复列表 (共4个回复)

沙发

1 make之后才生成dll
2 以编译时的错误为准,这个是提示功能出错,经常发生
3 implib是在只有dll,没有dll源代码情况下,用命令行生成lib的方式。此时dll由你自己编写,你拥有源代码,因此cb自动生成lib
4 cb是生成两个dll和lib
5 lib包含dll中导出函数和类的信息,反正implib可以生成lib所以可以自由选择是否生成
6 system32、windows或者应用程序文件夹

板凳

谢谢,再问个可能不容易回答的问题。
今天,我学会了编一个“输入一个数组,滤波、卷积后,再输出一个数组”的滤波器dll文件,
格式是:
extern"C" __declspec(dllexport) double *factor(double dx[])
{
//求出h[n],并与输入信号dx[n]进行卷积,得到输出信号dy[n]。
//return dy;

}

调用时,我采用的是隐式调用法。
我在想,很多人喜欢动态调用法,即LoadLibrary函数,但是,我在想,本dll输出给调用它的主程序的,实际上不是数组,而是一个指针,即*factor(double dx[])。

这种指针,如何采用动态调用法呢?
难道是这样写:
double  *(*dllfunc)(double[]);
hHandle=LoadLibrary(括号中写dll文件的地址);

*dllfunc已经是个指针了,这里为了把DLL里的数组调出来,又要用上指针,岂不成了“指针的指针”???

3 楼

你这样写是对的,double*表示返回值类型,*dllfunc表示函数指针。
不过按你的写法dy的空间再dll内部申请,而在dll外部释放,有会迷惑使用者。如下编写会更好:
extern"C" __declspec(dllexport) void factor(double dx[],double dy[])
{
//求出h[n],并与输入信号dx[n]进行卷积,得到输出信号dy[n]。
//return dy;
}
调用也明确了:
void (*dllfunc)(double[],double[]);
ps. 你是学数字信号的吧

4 楼

受教了。

是啊,俺是学数字信号处理的,《borland c++6》加上《C++》,《matlab》,《数字信号处理》加上《信号与系统》,三大类知识,是俺要克服的难关。

气煞俺了,一个小小陷波器用上三类知识,俺一个也不精通,都是新手。

我来回复

您尚未登录,请登录后再回复。点此登录或注册