Skip to main content

Guide to Creating and Executing C Executables with Shared Libraries and Java Integration

Guide to Creating and Executing C Executables with Shared Libraries and Java Integration

1. Compiling a C Program to an Executable

Step 1: Write a C Program

#include <stdio.h>

int main() {
    printf("Hello, World!\\n");
    return 0;
}

Step 2: Compile the C Program

gcc -o example example.c

2. Executing the C Program in the Console

Step 3: Run the Executable

./example

3. Including Shared .so Libraries

Step 4: Create a Shared Library

#include <stdio.h>

void my_function() {
    printf("Shared Library Function Called!\\n");
}
gcc -shared -o libmylib.so -fPIC mylib.c

Step 5: Update the C Program to Use the Shared Library

#include <stdio.h>

void my_function();

int main() {
    my_function();
    printf("Hello, World!\\n");
    return 0;
}
gcc -o example example.c -L. -lmylib

4. Temporarily Modifying Environment Variables

Step 6: Set the LD_LIBRARY_PATH

LD_LIBRARY_PATH=. ./example

5. Executing the Executable from Java

Step 7: Java Code to Execute the C Program

import java.io.*;
import java.util.*;

public class RunCProgram {

    public static void main(String[] args) {
        String executablePath = "./example";
        String libraryPath = ".";

        try {
            // Path to the compiled C program
            System.out.println("Executable Path: " + executablePath);

            // Verify if the file exists and has execute permissions
            File file = new File(executablePath);
            if (!file.exists()) {
                System.err.println("The specified file does not exist: " + executablePath);
                return;
            }
            if (!file.canExecute()) {
                System.err.println("The specified file is not executable: " + executablePath);
                return;
            }

            // Use ProcessBuilder to set environment variables
            ProcessBuilder builder = new ProcessBuilder(executablePath);

            // Set the LD_LIBRARY_PATH and other environment variables
            Map environment = builder.environment();
            environment.put("LD_LIBRARY_PATH", libraryPath);

            // Copy all environment variables from system console to Java process
            Process envProcess = Runtime.getRuntime().exec("printenv");
            BufferedReader envReader = new BufferedReader(new InputStreamReader(envProcess.getInputStream()));
            String envLine;
            while ((envLine = envReader.readLine()) != null) {
                String[] keyValue = envLine.split("=", 2);
                if (keyValue.length == 2) {
                    environment.put(keyValue[0], keyValue[1]);
                }
            }

            System.out.println("Environment Variables:");
            for (Map.Entry entry : environment.entrySet()) {
                System.out.println(entry.getKey() + ": " + entry.getValue());
            }

            // Start the process
            Process process = builder.start();

            // Get the input stream (output of the C program)
            captureStream(process.getInputStream(), System.out, "Output of the C program:");

            // Get the error stream (to check for any errors during execution)
            captureStream(process.getErrorStream(), System.err, "Errors (if any):");

            // Wait for the process to complete and return the exit code
            int exitCode = process.waitFor();
            System.out.println("C program exited with code: " + exitCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void captureStream(InputStream stream, PrintStream output, String header) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        String line;
        output.println(header);
        while ((line = reader.readLine()) != null) {
            output.println(line);
        }
    }
}

6. Copy Environment Variables to Java in Eclipse

Step 8: Generate Environment Variables File in Console

printenv > env_vars.txt

Step 9: Read Environment Variables File in Java

import java.io.*;
import java.util.*;

public class RunCProgram {

    public static void main(String[] args) {
        String executablePath = "./example";
        String libraryPath = ".";

        try {
            // Path to the compiled C program
            System.out.println("Executable Path: " + executablePath);

            // Verify if the file exists and has execute permissions
            File file = new File(executablePath);
            if (!file.exists()) {
                System.err.println("The specified file does not exist: " + executablePath);
                return;
            }
            if (!file.canExecute()) {
                System.err.println("The specified file is not executable: " + executablePath);
                return;
            }

            // Use ProcessBuilder to set environment variables
            ProcessBuilder builder = new ProcessBuilder(executablePath);

            // Set the LD_LIBRARY_PATH and other environment variables
            Map environment = builder.environment();
            environment.put("LD_LIBRARY_PATH", libraryPath);

            // Copy environment variables from env_vars.txt file
            try (BufferedReader envReader = new BufferedReader(new FileReader("env_vars.txt"))) {
                String envLine;
                while ((envLine = envReader.readLine()) != null) {
                    String[] keyValue = envLine.split("=", 2);
                    if (keyValue.length == 2) {
                        environment.put(keyValue[0], keyValue[1]);
                    }
                }
            }

            System.out.println("Environment Variables:");
            for (Map.Entry entry : environment.entrySet()) {
                System.out.println(entry.getKey() + ": " + entry.getValue());
            }

            // Start the process
            Process process = builder.start();

            // Get the input stream (output of the C program)
            captureStream(process.getInputStream(), System.out, "Output of the C program:");

            // Get the error stream (to check for any errors during execution)
            captureStream(process.getErrorStream(), System.err, "Errors (if any):");

            // Wait for the process to complete and return the exit code
            int exitCode = process.waitFor();
            System.out.println("C program exited with code: " + exitCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void captureStream(InputStream stream, PrintStream output, String header) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        String line;
        output.println(header);
        while ((line = reader.readLine()) != null) {
            output.println(line);
        }
    }
}

Comments

Popular posts from this blog

How to Add External Libraries (JAR files) in Eclipse

How to Add External Libraries (JAR files) in Eclipse Adding external libraries (JAR files) to your Eclipse project allows you to use third-party code in your application. This guide will explain what JAR files are, how they differ from `.java` files, where to download them, and how to add them to your project. What are JAR Files? JAR (Java ARchive) files are package files that aggregate many Java class files and associated metadata and resources (such as text, images, etc.) into a single file for distribution. They are used to distribute Java programs and libraries in a platform-independent format, making it easier to share and deploy Java applications. Difference between .java and .jar Files .java files are source files written in the Java programming language. They contain human-readable Java code that developers write. In contrast, .jar files are compile...

Managing Hierarchical Structures: OOP vs Nested Maps in Java

Managing Hierarchical Structures: OOP vs Nested Maps in Java This topic explores the pros and cons of managing hierarchical data using Object-Oriented Programming (OOP) versus nested map structures in Java. This discussion is contextualized with an example involving a chip with multiple cores and sub-cores. Nested Map of Maps Approach Using nested maps to manage hierarchical data can be complex and difficult to maintain. Here’s an example of managing a chip with cores and sub-cores using nested maps: Readability and Maintainability: Nested maps can be hard to read and maintain. The hierarchy is not as apparent as it would be with OOP. Encapsulation: The nested map approach lacks encapsulation, leading to less modular and cohesive code. Error-Prone: Manual management of keys and values increases the risk of errors, such as NullPointerExce...