C++ in Prolog. how to get the result in a variable?

#include <SWI-Prolog.h>
#include <iostream>
#include <string>
#include <vector>
#include <cctype>

// Global array to store detected variables
std::vector<std::string> detected_variables;

// Function to analyze and detect variables in a query
int process_query(const std::string &query) {
    detected_variables.clear(); // Reset the detected variables

    std::string current_term; // Store the current term
    bool after_equals = false; // Indicates if we're after an '=' sign

    for (size_t i = 0; i < query.size(); ++i) {
        char c = query[i];

        // Stop processing if a period ('.') is reached
        if (c == '.') {
            // Check the last term before exiting
            if (after_equals && !current_term.empty() && (isupper(current_term[0]) || current_term[0] == '_')) {
                detected_variables.push_back(current_term);
                std::cout << "Detected variable 1: " << current_term << std::endl;
            }
            break;
        }

        // Detect the '=' sign
        if (c == '=') {
            after_equals = true; // Switch to the right-hand side of the equality
            current_term.clear(); // Reset for the next term
            continue;
        }

        // Detect separators
        if (c == ',' || c == '[' || c == ']' || c == '(' || c == ')' || c == ' ') {
            if (!current_term.empty()) {
                // Check if the term starts with an uppercase letter or underscore and if we're after '='
                if (after_equals && (isupper(current_term[0]) || current_term[0] == '_')) {
                    detected_variables.push_back(current_term);
                    std::cout << "Detected variable 2: " << current_term << std::endl;
                }
                current_term.clear(); // Reset for the next term
            }
            continue;
        }

        // Append the character to the current term
        current_term += c;
    }

    return detected_variables.size();
}

// Function to display a Prolog list
void display_list(term_t list) {
    term_t head = PL_new_term_ref();
    term_t tail = PL_copy_term_ref(list);

    std::cout << "[";
    bool first = true;

    while (PL_get_list(tail, head, tail)) {
        if (!first) std::cout << ", ";
        first = false;

        char *element = nullptr;
        if (PL_get_chars(head, &element, CVT_WRITE | BUF_DISCARDABLE)) {
            std::cout << element;
        } else {
            std::cerr << "Error: Unable to extract an element from the list.\n";
        }
    }

    if (!PL_get_nil(tail)) {
        std::cerr << "Error: The term is not a well-formed list.\n";
    }

    std::cout << "]";
}

// Function to extract a list from a complex term or its subpart
bool extract_list(term_t term, const std::string &label) {
    term_t sub_term = PL_new_term_ref();

    // Check if the term is an equality functor (=) with two arguments
    if (PL_is_functor(term, PL_new_functor(PL_new_atom("="), 2))) {
        if (PL_get_arg(2, term, sub_term) && PL_is_list(sub_term)) {
            std::cout << label << " = ";
            display_list(sub_term);
            std::cout << std::endl;
            return true;
        }
    } else if (PL_is_list(term)) { // If the term is directly a list
        std::cout << label << " = ";
        display_list(term);
        std::cout << std::endl;
        return true;
    } else if (PL_is_functor(term, PL_new_functor(PL_new_atom("situation_facts"), 6))) {
        // Attempt to extract the 6th part for Facts
        if (PL_get_arg(6, term, sub_term) && PL_is_list(sub_term)) {
            std::cout << label << " = ";
            display_list(sub_term);
            std::cout << std::endl;
            return true;
        }
    }

    // On failure, display raw content for diagnostics
    char *term_str = nullptr;
    if (PL_get_chars(term, &term_str, CVT_WRITE | BUF_DISCARDABLE)) {
        std::cerr << label << " raw content: " << term_str << std::endl;
    } else {
        std::cerr << "Error: Unable to extract " << label << ".\n";
    }
    return false;
}

// Process and display solutions
void process_solution(term_t goal) {
    for (size_t i = 0; i < detected_variables.size(); ++i) {
        const std::string &variable_name = detected_variables[i];
        term_t variable_term = PL_new_term_ref();

        // Retrieve the argument corresponding to the variable
        if (PL_get_arg(static_cast<int>(i + 1), goal, variable_term)) {
            if (!extract_list(variable_term, variable_name)) {
                std::cerr << "Error: " << variable_name << " not readable or not formatted as a list.\n";
            }
        } else {
            std::cerr << "Error: Unable to extract " << variable_name << ".\n";
        }
    }
}

// Execute a user query
void execute_query(const std::string &query) {
    term_t goal = PL_new_term_ref();
    if (!PL_chars_to_term(query.c_str(), goal)) {
        std::cerr << "Error: Invalid input. Query ignored.\n";
        return;
    }

    predicate_t call_predicate = PL_predicate("call", 1, NULL);
    term_t args = PL_new_term_refs(1);
    PL_put_term(args, goal);

    qid_t query_id = PL_open_query(NULL, PL_Q_NORMAL, call_predicate, args);
    if (!query_id) {
        std::cerr << "Error: Unable to open the query.\n";
        return;
    }

    bool solution_found = false;
    while (PL_next_solution(query_id)) {
        solution_found = true;
        process_solution(goal); // Process the solution
    }

    if (!solution_found) {
        std::cout << "false." << std::endl; // Display false if no solution
    } else {
        std::cout << "false." << std::endl; // End with false after solutions
    }

    PL_close_query(query_id);
}

int main(int argc, char **argv) {
    if (!PL_initialise(argc, argv)) {
        std::cerr << "Error: Unable to initialize SWI-Prolog.\n";
        return 1;
    }

    const char *prolog_file = "/home/frank/DARBS/testeur_pro/src/helper_rulesx1.pl";
    term_t consult_term = PL_new_term_ref();
    std::string consult_command = "consult('" + std::string(prolog_file) + "').";

    if (!PL_chars_to_term(consult_command.c_str(), consult_term) || !PL_call(consult_term, NULL)) {
        std::cerr << "Error: Unable to load the Prolog file: " << prolog_file << "\n";
        PL_halt(1);
        return 1;
    }

    std::cout << "Prolog file loaded successfully.\n";

    std::string input;
    while (true) {
        std::cout << "Enter a Prolog query (or 'quit' to exit): ";
        std::getline(std::cin, input);

        if (input == "quit") break;

        process_query(input); // Dynamically store detected variables

        execute_query(input);
    }

    PL_halt(0);
    return 0;
}

i would like to have the result of my execution in a variable and print it.

Thanks

I don’t understand what you want to do here (and don’t have time to read through your code) … please be a bit more specific.

Your code doesn’t use the C++ API at all as far as I can tell. In general, the C++ API is quite a bit easier and less error-prone than the C API. If you want to use the C API, I suggest using the Plx_ versions of the functions.

Anyway, if you look in test_cpp.cpp, the following predicates (and how they’re called in test_cpp.pl) might help you:
call_cp_ex
can_unify
record_ext

Also, with_output_to/2 might be of use (e.g. with_output_to(string(Astr), write(current_output, A)).