mokky14's IT diary

IT関係の仕事メモ、勉強会の感想など書いてます。

C、C++ソース混在環境でのsqlcxtリンクエラー対処

Pro*Cを使ったソースのリンクで

undefined reference to `sqlcxt(void**, unsigned int*, sqlexd*, sqlcxp const*)'

というエラーでハマったのでメモ残しておく。

 

結論から書くと、今回コンパイルしようとしていたソースはC、C++ソース混在で、その場合はprocでのプリコンパイルはcode=cppでプリコンパイルしないとダメで、それをcode=ansi_cでプリコンパイルしてたのがダメだったというのがリンクエラーの原因。

以下、試した内容。

 

Pro*Cのバージョン:11.2

環境:CentOS 5.9

コンパイラ:g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-54)

 

こんなソース作って試してみた。サンプルなので動かないソースなのは気にしない。

#include <sqlca.h>
#include <stdio.h>

int commit(sql_context *context)
{
    struct    sqlca	sqlca;
    sqlca.sqlcode = 0;

    EXEC SQL CONTEXT USE :*context;
    EXEC SQL COMMIT;

    int code = sqlca.sqlcode;
    if (code != 0) {
        printf("error %s\n", sqlca.sqlerrm.sqlerrmc);
    }

    return(code);
}

int main() {
    commit(NULL);
}

上記ソースでcode=ansi_cとcode=cppでプリコンパイルしたソースを比較。関数定義がextern "C"{}で囲われているかそうでないかの違いがある。

$ proc iname=sample.pc code=ansi_c include=/usr/include/oracle/11.2/client64 oname=sample_ansi.c 

Pro*C/C++: Release 11.2.0.3.0 - Production on Thu Mar 21 09:30:06 2013

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

System default option values taken from: /usr/lib/oracle/11.2/client64/lib/precomp/admin/pcscfg.cfg

$ proc iname=sample.pc code=cpp include=/usr/include/oracle/11.2/client64 oname=sample_cpp.c

Pro*C/C++: Release 11.2.0.3.0 - Production on Thu Mar 21 09:30:14 2013

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

System default option values taken from: /usr/lib/oracle/11.2/client64/lib/precomp/admin/pcscfg.cfg

$ diff sample_ansi.c sample_cpp.c 
116,123c116,125
&lt /* SQLLIB Prototypes */
< extern void sqlcxt (void **, unsigned int *,
<                     struct sqlexd *, const struct sqlcxp *);
< extern void sqlcx2t(void **, unsigned int *,
<                     struct sqlexd *, const struct sqlcxp *);
< extern void sqlbuft(void **, char *);
< extern void sqlgs2t(void **, char *);
< extern void sqlorat(void **, unsigned int *, void *);
---
> // Prototypes
> extern "C" {
>   void sqlcxt (void **, unsigned int *,
>                struct sqlexd *, const struct sqlcxp *);
>   void sqlcx2t(void **, unsigned int *,
>                struct sqlexd *, const struct sqlcxp *);
>   void sqlbuft(void **, char *);
>   void sqlgs2t(void **, char *);
>   void sqlorat(void **, unsigned int *, void *);
> }
125c127
< /* Forms Interface */
---
> // Forms Interface
129c131
< extern void sqliem(unsigned char *, signed int *);
---
> extern "C" { void sqliem(unsigned char *, signed int *); }

 

code=ansi_cでプリコンパイルしたソースのコンパイル。

リンク時にsqlcxtのリンクエラー発生。

$ g++ sample_ansi.c -I/usr/include/oracle/11.2/client64 -L/usr/lib/oracle/11.2/client64/lib -lclntsh 
/tmp/cckOi2dx.o: In function `commit(void**)': sample_ansi.c:(.text+0xa0): undefined reference to `sqlcxt(void**, unsigned int*, sqlexd*, sqlcxp const*)' 
collect2: ld はステータス 1 で終了しました

 

code=cppでプリコンパイルしたソースのコンパイル。

コンパイル、リンクともエラーはなし。

$ g++ sample_cpp.c -I/usr/include/oracle/11.2/client64 -L/usr/lib/oracle/11.2/client64/lib -lclntsh
$

 

ということで、C++環境ではcode=cppでプリコンパイルする必要があるということでした。