您已经混合了调用,现在部分使用了 COBOL 运行时库 libcob,部分未使用它。通常您会执行以下操作之一(大多数时候是第三个选项):
只需将生成的 COBOL dll 用作“普通”dll,不关心任何清理
使用“干净”的运行时初始化和清理
使用选项并将 COBOL 模块的加载留给 libcob
选项 1:“最简单的解决方案” - 使用 COBOL 模块,无需清理
删除 C 源代码中对 libcob 的注释。
用 编译你的 COBOL 模块cobc -fimplicit-init filehandler.cob
,这样初始化是自动完成的。
注意:这会导致模块加载的额外启动时间最少(多少取决于正在使用的 libcob 版本,但通常不会太多)。
可能的问题:您没有清理 COBOL 部件的选项,在您完成(甚至关闭)模块句柄后它们仍将处于活动状态。
选项 2:“更清洁的解决方案,但仍涉及模块加载的系统特定部分”
编译您的 COBOL 模块,-fimplicit-init
并将您的代码更改为
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "libcob.h"
#ifdef __cplusplus
}
#endif
typedef void (*pFile)(char*);
pFile filehandler=NULL;
char dllpath[256];
int main(int argc, char *argv[])
{
HINSTANCE hLib;
char txt[100]="this is a test";
#if !defined PASS_COMMAND_LINE_TO_COBOL
cob_init(0, NULL); /* initialization of COBOL runtime, no command line passed */
#else
cob_init(argc, argv); /* initialization of COBOL runtime, complete command line passed */
#endif
hLib = LoadLibrary("F:\\source\\filehandler\\bin\\filehandler.dll");
if (!hLib)
{
perror("Error loading dll");
exit(1);
}
GetModuleFileName((HMODULE)hLib, (LPTSTR)dllpath, sizeof(dllpath));
printf("Opened %s\n\n", dllpath);
filehandler = (pFile)GetProcAddress((HMODULE)hLib, "filehandler");
if (!filehandler)
{
perror("Can't find dll function");
exit(1);
}
filehandler(txt);
#if defined (cob_c8_ptr) /* hack for checking if you use a 2.x+ version, not *really* needed in this case */
cob_tidy; /* finalizing of COBOL runtime (OC/GC function) */
#else
cobtidy; /* finalizing of COBOL runtime (MF compatibility function name available since OpenCOBOL 1.1 released Feb 2009 [still available (as define) in 2.x+ version]) */
#endif
return 0;
}
或(如果您真的想在 COBOL 调用后退出)将最后一个代码部分更改为:
int cob_return_int = filehandler(txt);
cob_stop_run (cob_return_int);
重要提示:您现在需要同时包含libcob.h
C 编译器以了解函数声明并链接到 libcob 库(很可能通过添加-lcob
到 DevC++ 中的编译器选项(否则您将从 C 链接器获得“未定义引用”消息)。
选项 3:“将所有 COBOL 都留给 libcob 的干净解决方案”
显然,在这种情况下,您也必须链接到 libcob。
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "libcob.h"
#ifdef __cplusplus
}
#endif
int main(int argc, char *argv[])
{
cob_call_union filehandler_module;
int cob_return_int;
char txt[100]="this is a test";
/* initialization of COBOL runtime, complete command line passed */
cob_init(argc, argv);
/* search and load a function pointer for program-id "filehandler" in a module called "filehandler" */
filehandler_module.funcvoid = cob_resolve ("filehandler");
if (filehandler_module.funcvoid == NULL) {
/* this will display the error and return with 1, as your old code did */
cob_call_error ();
/* if you just want the error text in a local buffer call `cob_resolve_error` instead */
}
/* calling the COBOL module "filehandler" and store its return-code in cob_return_int */
cob_return_int = filehandler_module.funcint(txt);
/* NOTE: you may call additional COBOL modules (or the same with a different option) here, maybe depending on `cob_return_int` */
cob_tidy; /* finalizing the COBOL runtime */
/* NOTE: more code goes here, likely handling `cob_return_int` */
return 0;
}
代码中唯一“缺少”的是“filehandler.dll”的路径。libcob 首先尝试当前路径,因此如果您的模块在那里,则无需调整它。
set COB_LIBRARY_PATH=F:\source\filehandler\bin
通过应用程序外部指定模块查找路径。
如果你真的想在你的应用程序中硬连线它并且有一个非常新的版本(读作“近乎当前的开发快照”)你可以通过调用来做到这一点cob_setenv("COB_LIBRARY_PATH", "F:\\source\\filehandler\\bin", 1);
- 这样做setenv()
或者putenv()
可能工作(但这高度依赖于 C 运行时库用于您的程序和 libcob。
如果可能的话,我总是建议(对于“当前”版本的 GnuCOBOL)使用运行时配置文件set COB_RUNTIME_CONFIG=X:\PATH\TO\filehandler.cfg
并使用上面概述的环境函数指定其路径。
如果您使用比 GnuCOBOL 2.2rc 更旧的任何东西,我总是建议切换到最新版本的 GnuCOBOL,但这是一个不同的问题......