我正在尝试使用开发人员C++集成开发环境从一个用C编写的程序中调用一个OpenCobol文件处理例程(它们是免费的,我喜欢它们)。
当您将代码编译为模块时,Cobol环境会生成一个DLL,所以我希望我可以只使用调用代码的普通方法(见下文)。如果按照下面的方式编译和运行,我会得到错误消息"libcob: cob_init()尚未被调用“,然而,在相关位置包含头文件和库并取消代码中的部分注释后,我得到了一条”未定义的对_imp_cob_init的引用“消息。
我显然遗漏了一些简单的东西。任何帮助都将不胜感激。
AdyB
#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";
/* cob_init(0, NULL);*/
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);
return 0;
}发布于 2017-08-28 20:05:35
您已经混合了这两个调用,现在部分使用了COBOL运行时库libcob,部分不使用它。通常,您可以执行以下操作之一(大多数情况下是第三个选项):
cleanup
完成。
选项1:“最简单的解决方案”-使用COBOL模块,无需清理
删除C源代码中libcob的注释。
用cobc -fimplicit-init filehandler.cob编译你的COBOL模块,这样初始化就会自动完成。
注意:这会导致模块加载的额外启动时间最短(具体多少取决于所使用的libcob版本,但一般不会太多)。
可能的问题:您没有清理COBOL部分的选项,在您完成(甚至关闭)模块句柄后,它们仍将处于活动状态。
选项2:“更干净的解决方案,但仍然涉及模块加载的系统特定部分”
在没有-fimplicit-init的情况下编译COBOL模块,并将代码更改为
#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()可以做到这一点(但这在很大程度上依赖于用于你的程序和libcob的C运行时库。
如果可能,我总是建议(对于GnuCOBOL的“当前”版本)使用runtime configuration file,并用set COB_RUNTIME_CONFIG=X:\PATH\TO\filehandler.cfg或上面概述的环境函数指定它的路径。
如果你使用的是比GnuCOBOL 2.2rc更早的版本,我总是建议你改用最新版本的GnuCOBOL,但这是另一个问题……
https://stackoverflow.com/questions/45906990
复制相似问题