PRO*C 解決可變參數函數編譯錯誤問題

此次問題總結

1.工程中用到##拼接宏,該宏proc無法識別(文檔記載)-頭文件進行重新整合,後續樣例。
2.typedef int hhh_t 該在parse=none時無法識別(根據調整選項時的經驗)-選項使用parse=full默認的好像也是這個。
3.除一些可以識別的系統頭文件,加入proc預編譯會core-頭文件需要重新整合。
4.找不到自定義相關文件的頭,加入選項include={…/inc1/,…/include2/}即可,內容爲自定義文件的目錄路徑
5.找不到系統頭文件,加入選項sys_include={/usr/include/}即可,內容爲對應系統文件頭的目錄路徑。該情況加入頭以後仍無法解決,需判斷是否需要該系統頭文件,是否需要將相關無用的頭文件交予gcc而不是proc-即ORA_PROC宏的使用

其他以前遇到的問題

1.程序沒有使用多線程,結果編譯參數threads=yes 編譯錯誤-解決方法去掉該編譯選項即可

proc工具官方文檔地址

https://docs.oracle.com/database/121/LNPCC/toc.htm

此次解決過程

首先一開始編譯按照C語言的頭文件規則把所有的頭都加進去了,然後再proc的預編譯解階段core掉了,生成一個core文件,沒辦法找出原因,然後百度和必應查找都沒有找到原因,網上各種解決方法都是sys_include選項修改增加,全部無法解決我遇到的問題。我的pc文件有接近20w行。
裏面用到靜態嵌入sql,動態嵌入sql。在我懷疑是代碼問題的時候,我把代碼從上到下由1個函數到6個函數進行預編譯,發現在進行有個動態嵌入sql的時候出現了問題。把改函數單獨拿出來也有問題。
期間,搜索到有人遇到過文件名太長的錯誤,造成proc編譯core掉
https://www.cnblogs.com/kingstarer/p/12079989.html
1.猜測頭文件路徑問題,修改各種編譯選項並適配編譯路徑仍無法解決,排除該問題。
2.猜測程序嵌入部分代碼段問題,通過把該函數刪掉只剩下宿主變量聲明的時候還是編譯異常,排除代碼段問題。
3.猜測頭文件#include 問題,重新閱讀oracle提供的預編譯文檔,其中有記路可識別的和不可識別的。將可以識別的包含,自定義的簡單宏定義在mymacrodef.h文件中

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"mymacrodef.h"

在其他頭文件裏面定義了宏表示宿主變量的數組大小 結果沒有#include 然後報告

PCC-S-02322 ,found undefine identifier
Semantic error at line xxxx,column xxx,file xx.pc

我把帶有相關宏定義頭帶進去
然後 又

PCC-S-02201,Encountered the symbol "size_t" when expecting one of  the  following  :
char,const,double  等等

我去看了一下相關頭 ,裏面還有一些pthread.h sys/call.h等等 我猜想 PROC 閱讀能力不高端 有些宏定義無法識別(詳細oracle的嵌入式SQL) 而且一些類型名被重命名 ,所以出錯,
編譯選項 parse=full 才能通過,因此我把頭分開 能識別的宏定義和類型 弄到pc文件裏面 不能識別的用於後續gcc編譯的聲明放入
#ifndef ORA_PROC
#include"其他"
#endif

樣例詳情

#文件樹結構
work_disk
├─.src
│  └─test.pc
├─.include2
│  ├─mymacrodef.h
│  └─procafter.h
/*test.pc*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"mymacrodef.h"
#ifndef  ORA_PROC
#include"procafter.h"
#endif

int_ty foo(int_ty a)
{
EXEC SQL BEGIN DECLARE SECTION;
  int_ty  aary[QUEUE_SIZE][20];  -- Declare host  variable.
EXEC SQL END DECLARE SECTION;
printfmylog("foo","indexs:%d",sizeof(array)/sizeof(int_ty));
}
/*mymacrodef.h*/
#ifndef MYMACRODEF__H_
#define MYMACRODEF__H_
typedef int int_ty;
#define QUEUE_SIZE 44
#endif
/*procafter.h*/
#ifndef PROCAFTER__H_
#define PROCAFTER__H_
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include<time.h>
#include"mymacrodef.h"
#define printmylog(str,f,...)  printf("%s" f,str,##__VA_ARGS__);
#endif

#makefile test part
CC=gcc
PROC=proc
CCINCLUDE= -I./  -I../include2/
LINKLIBS= -L$(ORACLE_HOME)/lib/ -lclntsh
PROCOPTION= parse=full include={./,../include2/} lines=yes 
test.o:test.pc
	$(PROC) $(PROCOPTION) iname=test.pc
	$(CC)  $(CCINCLUDE) -c  test.c

PS:我的改動後又遇到undefined reference 這個是我makefile中的

LINKLIBS+= -L$(ORACLE_HOME)/lib/  -lclntsh  
#寫錯成$(LINKLIBS)開頭了

相關原文資源截取

ORA_PROC Macro

ora_proc :https://docs.oracle.com/database/121/LNPCC/pc_05adv.htm#LNPCC3289

Pro*C/C++ predefines a C preprocessor macro called ORA_PROC that you can use to avoid having the precompiler process unnecessary or irrelevant sections of code. Some applications include large header files, which provide information that is unnecessary when precompiling. By conditionally excluding such header files based on the ORA_PROC macro, the precompiler never reads the file.

The following example uses the ORA_PROC macro to exclude the irrelevant.h file:

#ifndef  ORA_PROC
#include <irrelevant.h>
#endif

Because ORA_PROC is defined during precompilation, the irrelevant.h file is never included.

The ORA_PROC macro is available only for C preprocessor directives, such as #ifdef or #ifndef. The EXEC ORACLE conditional statements do not share the same namespaces as the C preprocessor macros. Therefore, the condition in the following example does not use the predefined ORA_PROC macro:

EXEC ORACLE IFNDEF ORA_PROC;
   <section of code to be ignored>
EXEC ORACLE ENDIF;

ORA_PROC, in this case, must be set using either the DEFINE option or an EXEC ORACLE DEFINE statement for this conditional code fragment to work properly.

Directives Ignored被忽略的宏定義指令

Some C preprocessor directives are not used by the Pro*C/C++ preprocessor. Most of these directives are not relevant for the precompiler. For example, #pragma is a directive for the C compiler—the precompiler does not process it. The C preprocessor directives not processed by the precompiler are:
#, to convert a preprocessor macro parameter to a string constant

##, to merge two preprocessor tokens in a macro definition

#error, to produce a compile-time error message

#pragma, to pass implementation-dependent information to the C compiler

#line, to supply a line number for C compiler messages

Preprocessor Directives 預編譯器proc指令

The preprocessor directives that Pro*C/C++ supports are:

#define, to create macros for use by the precompiler and the C or C++ compiler

#include, to read other source files for use by the precompiler

#if, to precompile and compile source text based on evaluation of a constant expression to 0

#ifdef, to precompile and compile source text conditionally, depending on the existence of a defined constant

#ifndef, to exclude source text conditionally

#endif, to end an #if or #ifdef or #ifndef command

#else, to select an alternative body of source text to be precompiled and compiled, in case an #if or #ifdef or #ifndef condition is not satisfied

#elif, to select an alternative body of source text to be precompiled and compiled, depending on the value of a constant or a macro argument


錯誤列表可以去Oracle的錯誤集查找 或者下面一篇博文
《Pro*C 錯誤的詳細信息以及解決方法(收下備用)》https://blog.csdn.net/luolunz/article/details/9211259?utm_source=app

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章