如何获取在外部库中定义为 char** 的 C(CDELC) 函数的输出值

How do you get the output value of a C(CDELC) function defined in an external library as char**

我希望能够使用在共享对象文件 (lib.so) 中定义的以下函数:

int encrypt_data (char* buffer_in, int size_in, char** buffer_out, int* size_out)

基本上,我希望能够将文件的内容传递给此函数 (buffer_in) 并将输出内容 (buffer_out) 写入另一个文件。这是我到目前为止尝试过的方法:

PROCEDURE encrypt_data EXTERNAL  "lib.so" CDECL :
    DEFINE INPUT PARAMETER buffer_in        AS MEMPTR.
    DEFINE INPUT PARAMETER size_in          AS LONG.
    DEFINE OUTPUT PARAMETER buffer_out      AS MEMPTR.
    DEFINE OUTPUT PARAMETER size_out        AS LONG.
    DEFINE RETURN PARAMETER returnvalue     AS LONG.
END PROCEDURE.

PROCEDURE pi_encryptHash:
    DEFINE INPUT  PARAMETER ipc_fullPathToEncrypt  AS CHARACTER   NO-UNDO.
    DEFINE VARIABLE lm_bufferIn            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE li_sizeIn              AS INT       NO-UNDO.
    DEFINE VARIABLE lm_bufferFakeOut            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE lm_bufferOut            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE li_sizeOut             AS INT       NO-UNDO.
    DEFINE VARIABLE li_returnedCode          AS INTEGER NO-UNDO.

    /* make sure MEMPTR is sized correctly */
    FILE-INFO:FILE-NAME = ipc_fullPathToEncrypt.
    SET-SIZE(lm_bufferIn) = FILE-INFO:FILE-SIZE.
    li_sizeIn = GET-SIZE(lm_bufferIn).

    /* the actual read */
    INPUT FROM VALUE(ipc_fullPathToEncrypt) BINARY NO-MAP NO-CONVERT.
    IMPORT lm_bufferIn.
    INPUT CLOSE.

    /* Call the encrypt proc a first time to get the output lenght */
    SET-SIZE(lm_bufferFakeOut) = 2.
    RUN encrypt_data(INPUT lm_bufferIn, INPUT li_sizeIn, OUTPUT lm_bufferFakeOut, OUTPUT li_sizeOut, OUTPUT li_returnedCode).

    /* Call it a second time with a buffer large enough to get the output value */
    SET-SIZE(lm_bufferOut) = li_sizeOut.
    RUN encrypt_data(INPUT lm_bufferIn, INPUT li_sizeIn, OUTPUT lm_bufferOut, OUTPUT li_sizeOut, OUTPUT li_returnedCode).

    /* Write MEMPTR to file */
    OUTPUT TO VALUE(ipc_fullPathToEncrypt + ".sha") BINARY NO-MAP NO-CONVERT.
    EXPORT lm_bufferOut.
    OUTPUT CLOSE.

    SET-SIZE(lm_bufferIn) = 0.
    SET-SIZE(lm_bufferOut) = 0.

    DISPLAY li_returnedCode.

    RETURN "".

END PROCEDURE.

我想我的问题是我无法读取 char** buffer_out 的数据,据我所知,它是一个指向指针的指针,所以我在这里 EXPORT lm_bufferOut. 真正导出的是我要导出的数据的指针地址?但是我怎样才能导出数据呢?

可能不是您原来问题的答案,但请注意,正在进行加密的内置函数。例如,您可以这样做(在此示例中,加密值是 base64 编码的,因此结果是 "viewable"):

DEFINE VARIABLE cClearText      AS CHARACTER NO-UNDO.
DEFINE VARIABLE rBinaryKey      AS RAW       NO-UNDO.
DEFINE VARIABLE rEncryptedValue AS RAW       NO-UNDO.
DEFINE VARIABLE cEncryptedText  AS CHARACTER NO-UNDO.
DEFINE VARIABLE cDecryptedText  AS CHARACTER NO-UNDO.

ASSIGN
    cClearText = "This is the clear text string to be encrypted.".

MESSAGE "Original message: " cCleartext
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

ASSIGN 
    SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM = "AES_OFB_256"
    rBinaryKey = GENERATE-RANDOM-KEY
    SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = rBinaryKey
    SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?
    rEncryptedValue = Encrypt (cClearText)
    cEncryptedText = BASE64-ENCODE(rEncryptedValue)
    .

MESSAGE "Encrypted Message:" cEncryptedText
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

ASSIGN
    SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = rBinaryKey
    cDecryptedText = GET-STRING(DECRYPT (rEncryptedValue),1).

MESSAGE "Decrypted Message: " cDecryptedText
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

此示例基于 this knowledge base entry

你可以这样做:

MESSAGE SECURITY-POLICY:SYMMETRIC-SUPPORT VIEW-AS ALERT-BOX.

查看支持的对称加密算法。

这是一个关于不同版本的 AES 算法的 SO 问题:

How to choose an AES encryption mode (CBC ECB CTR OCB CFB)?

已找到解决方法,下面是使用的程序:

PROCEDURE pi_encryptDecrypt:
    DEFINE INPUT  PARAMETER ipc_inputFile  AS CHARACTER   NO-UNDO.
    DEFINE INPUT  PARAMETER ipc_outputFile  AS CHARACTER   NO-UNDO.
    DEFINE INPUT  PARAMETER ipi_codeOp     AS INTEGER     NO-UNDO.

    DEFINE VARIABLE lm_bufferIn            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE li_sizeIn              AS INT       NO-UNDO.
    DEFINE VARIABLE lm_bufferFakeOut            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE lm_bufferOut            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE li_sizeOut             AS INT       NO-UNDO.
    DEFINE VARIABLE li_returnedCode          AS INTEGER NO-UNDO.
    define variable mtarget as memptr.

    /* make sure MEMPTR is sized correctly */
    FILE-INFO:FILE-NAME = ipc_inputFile.
    SET-SIZE(lm_bufferIn) = FILE-INFO:FILE-SIZE.
    li_sizeIn = GET-SIZE(lm_bufferIn).

    /* the actual read */
    copy-lob from file ipc_inputFile to lm_bufferIn.


    /* set a buffer large enough to get the output value */
    SET-SIZE(lm_bufferOut) = 8.

    if ipi_codeOp = 1 then
        RUN encrypt_data(INPUT lm_bufferIn, INPUT li_sizeIn, OUTPUT lm_bufferOut, OUTPUT li_sizeOut, OUTPUT li_returnedCode).
    else
        RUN decrypt_data(INPUT lm_bufferIn, INPUT li_sizeIn, OUTPUT lm_bufferOut, OUTPUT li_sizeOut, OUTPUT li_returnedCode).

    set-size(mtarget) = li_sizeOut.
    SET-POINTER-VALUE(mtarget) = GET-INT64(lm_bufferOut, 1).


    /* Write MEMPTR to file */
    os-delete value(ipc_outputFile).
    COPY-LOB FROM mtarget for /* FOR est SUPER IMPORTANT !! - ne pas enlever */ li_sizeOut TO FILE (ipc_outputFile).


    SET-SIZE(lm_bufferIn) = 0.
    SET-SIZE(lm_bufferOut) = 0.
    set-size(mtarget) = 0.

    /*DISPLAY li_returnedCode.
    DISPLAY li_sizeOut.*/

    RETURN "".
END PROCEDURE.

正如我在问题中所述,问题确实是 char** buffer_out returns 指向内存中数据的指针。

诀窍是使用第二个 MEMPTR (mtarget),它将指向实际数据,使用 SET-SIZE 将其大小设置得足够大,然后将其设置为特定内存位置的值(使用SET-POINTER-VALUE),我们从 GET-INT64(lm_bufferOut, 1).

得到