cancel
Showing results for 
Search instead for 
Did you mean: 

SAP RFC connection from C/C++ (cia Cmake) - error with no description

shokarta
Explorer
0 Kudos

Hello gurus,

I am trying to establish a connection from c++ application (via QT, but its pretty much same as Visual Studio).

So what I did... i have downloaded and extracted newest nwrfcsdk and set the path variables to there/lib, and also SAPNWRFC_HOME to that nwrfcsdk folder. upon running nwrfcsdk/bin/rfcexec.exe proves PATH is fine.

Then, in Cmake i did linked the libs and includes:

<code>set(SAPNWRFC_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/nwrfcsdk/include")
set(SAPNWRFC_LIB_DIR "${PROJECT_SOURCE_DIR}/nwrfcsdk/lib")
set(SAPNWRFC_LIB_FILES sapnwrfc.lib libsapucum.lib)

target_link_directories(appsap_rtf PRIVATE ${SAPNWRFC_LIB_DIR})

target_link_libraries(appsap_rtf
    PRIVATE Qt6::Quick
    PRIVATE ${SAPNWRFC_LIB_FILES})

qt_add_executable(appsap_rtf companyClient.cpp)

and then I tried very basic example from SAP NetWeaver RFC SDK:

companyClient.cpp:

<code>#include <stdlib.h>
#include <stdio.h>
#include "nwrfcsdk/include/sapnwrfc.h"

void errorHandling(RFC_RC rc, SAP_UC* description, RFC_ERROR_INFO* errorInfo, RFC_CONNECTION_HANDLE connection){
    printfU(cU("%s: %d\n"), description, rc);
    printfU(cU("%s: %s\n"), errorInfo->key, errorInfo->message);
    // It's better to close the TCP/IP connection cleanly, than to just let the
    // backend get a "Connection reset by peer" error...
    if (connection != NULL) RfcCloseConnection(connection, errorInfo);

    exit(1);
}

//usage: companyClient <hostname> <system Number> <client> <user> <language> <password>
int mainU(int argc, SAP_UC** argv){
    RFC_RC rc = RFC_OK;
    RFC_CONNECTION_PARAMETER loginParams[6];
    RFC_ERROR_INFO errorInfo;
    RFC_CONNECTION_HANDLE connection;
    RFC_FUNCTION_DESC_HANDLE bapiCompanyDesc;
    RFC_FUNCTION_HANDLE bapiCompany;
    RFC_STRUCTURE_HANDLE returnStructure;
    SAP_UC message[221] = iU("");
    RFC_BYTE buffer[1105];
    unsigned utf8Len = 1105, resultLen;
    FILE* outFile;

    loginParams[0].name = cU("ashost"); loginParams[0].value = cU("****"); // hostname
    loginParams[1].name = cU("sysnr");  loginParams[1].value = cU("**");   // system number
    loginParams[2].name = cU("client"); loginParams[2].value = cU("***");  // client number
    loginParams[3].name = cU("user");   loginParams[3].value = cU("*****"); // username
    loginParams[4].name = cU("passwd"); loginParams[4].value = cU("*****");  // password
    loginParams[5].name = cU("lang");   loginParams[5].value = cU("EN");

    connection = RfcOpenConnection(loginParams, 6, &errorInfo);
    if (connection == NULL) errorHandling(rc, cU("Error during logon"), &errorInfo, NULL);

    bapiCompanyDesc = RfcGetFunctionDesc(connection, cU("BAPI_COMPANY_GETDETAIL"), &errorInfo);
    if (bapiCompanyDesc == NULL) errorHandling(rc, cU("Error during metadata lookup"), &errorInfo, connection);

    bapiCompany = RfcCreateFunction(bapiCompanyDesc, &errorInfo);

    // Use a company ID that does not exit. 000007 should not exist in most systems.
    RfcSetChars(bapiCompany, cU("COMPANYID"), cU("000007"), 6, &errorInfo);

    rc = RfcInvoke(connection, bapiCompany, &errorInfo);
    if (rc != RFC_OK) errorHandling(rc, cU("Error calling BAPI_COMPANY_GETDETAIL"), &errorInfo, connection);

    RfcGetStructure(bapiCompany, cU("RETURN"), &returnStructure, &errorInfo);
    RfcGetString(returnStructure, cU("MESSAGE"), message, 221, &resultLen, &errorInfo);
    RfcDestroyFunction(bapiCompany, &errorInfo);
    RfcCloseConnection(connection, NULL);

    // On Windows you can use the following function from windows.h toconvert to UTF-8:
    // utf8Len = WideCharToMultiByte(CP_UTF8, 0, message, strlenU(message), buffer, 1105, NULL, NULL);
    // It will have a slightly better performance than RfcSAPUCToUTF8().
    
    // On 'system i' with Japanese double byte characters using the ASCII LIBSAPNRFC the
    // message string does not contain UNICODE but JIS encoded data. The call to the
    // following function does not make any sense in this case. Instead you can add an
    // encoding to the header lilke this: "<?xml version=\"1.0\" encoding=\"Shift-JIS\"?>\n<message>",
    // and fputs the message directly some lines below:
    // fwrite(buffer, 1, utf8Len, outFile); ==> fputs((char*)message, outFile);
    /*CCQ_SECURE_LIB_OK*/
    RfcSAPUCToUTF8(message,  strlenU(message), buffer, &utf8Len,  &resultLen, &errorInfo);

    outFile = fopenU(cU("message.xml"), cU("w"));
    if (!outFile) return 1;

    /*SAPUNICODEOK_STRINGCONST*/ /*SAPUNICODEOK_LIBFCT*/
    fputs("<?xml version=\"1.0\"?>\n<message>", outFile);
    /*SAPUNICODEOK_LIBFCT*/
    fwrite(buffer, 1, utf8Len, outFile); // See comment above for system i
    /*SAPUNICODEOK_STRINGCONST*/ /*SAPUNICODEOK_LIBFCT*/
    fputs("</message>", outFile);
    fclose(outFile);

    // Now view the message.xml file in a standard browser that supports UTF-8, and you should
    // be able to view the Japanese characters.

    return 0;
}

however, upon trying to run it, i have only this debug infro from the console:

<code>Error during logon: 0
R: 

I'm 100% of the login data as I use them from other apps from same device (i.e. connecting Excel VBA vba sap references).

The only difference is that other apps requires the loginParameter also "system" (in SAP SDK documentation its as "sysid" or "r3name" or "dest", which I tried all of them but with same result.... tho other apps wont log in without this sysid parameter... so could be the problem, but i doubt it as it would give me some error description.

here now I am lost and don't know how to find out why my connection is being refused with no error description.

Accepted Solutions (1)

Accepted Solutions (1)

Ulrich_Schmidt
Product and Topic Expert
Product and Topic Expert
0 Kudos

Most probably, you did not set the pre-processor define "SAPwithUNICODE"? (It's not mentioned in your Cmake snippet from above.) If that is not set, your compiler will treat all logon parameters (and other stuff as well...) as 1-byte-per-char ASCII, while the sapnwrfc.dll will try to interpret the data as 2-byte-per-char Unicode! This will of course result in garbage (sometimes even in crashes due to memory access violation, if the lib tries to read more bytes than there are...)

See SAP note 2573953 for all necessary compiler options, when compiling programs that use the sapnwrfc.dll.

Answers (1)

Answers (1)

shokarta
Explorer
0 Kudos

Thank you ulrich.schmidt,

this actually helped and there is no error anymore while i run the program:

#target_compile_definitions(appsap_rtf PRIVATE SAPwithUNICODE UNICODE _UNICODE SAPwithTHREADS)
target_compile_definitions(appsap_rtf PRIVATE SAPwithUNICODE)
target_compile_definitions(appsap_rtf PRIVATE UNICODE)
target_compile_definitions(appsap_rtf PRIVATE _UNICODE)
target_compile_definitions(appsap_rtf PRIVATE SAPwithTHREADS)

hope this helps someone in the future