Cross-Platform Dynamic Library Creation and Consumption in C++, C#, and Java
Creating Dynamic Libraries
Windows DLL Development
To create a Windows dynamic link library, start by establishing a DLL project. The core functionality is implemented in the source file:
#include "framework.h"
extern "C" __declspec(dllexport) int addValues(int x, int y) {
return x + y;
}
BOOL APIENTRY DllMain(HMODULE module, DWORD callReason, LPVOID reserved) {
switch (callReason) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
The corresponding header defines the exported function:
#ifndef FRAMEWORK_H
#define FRAMEWORK_H
#include <windows.h>
#endif
extern "C" __declspec(dllexport) int addValues(int x, int y);
Build the project in Release configuration to genertae the DLL file.
Linux Shared Object Creation
For Linux platforms, create a shared object file using:
extern "C" {
int calculateSum(int first, int second) {
return first + second;
}
}
Compile this source to produce a .so file.
Consuming Libraries
C++ Application Integration
Create a new executable project and implement library loading:
#include <iostream>
#include <windows.h>
typedef int (*sumFunction)(int, int);
int main() {
HMODULE libraryHandle = LoadLibrary(L"mathlibrary.dll");
if (libraryHandle) {
std::cout << "Library loaded successfully\n";
sumFunction addFunc = (sumFunction)GetProcAddress(libraryHandle, "addValues");
if (addFunc) {
std::cout << "Function call result: " << addFunc(150, 250) << std::endl;
} else {
std::cout << "Function not found\n";
}
FreeLibrary(libraryHandle);
} else {
std::cout << "Failed to load library\n";
}
return 0;
}
Place the compiled DLL in the executable directory before running.
C# Integration
Define P/Invoke signatures for native library access:
using System.Runtime.InteropServices;
internal static class MathBridge
{
private const string WindowsLibrary = "mathlibrary.dll";
private const string LinuxLibrary = "libmathlibrary.so";
[DllImport(WindowsLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int addValues(int operand1, int operand2);
[DllImport(LinuxLibrary, CallingConvention = CallingConvention.Cdecl)]
public static extern int calculateSum(int operand1, int operand2);
}
Consume the native functions in application code:
using System;
class Program
{
static void Main()
{
int result = MathBridge.addValues(12, 1000);
Console.WriteLine($"Computed sum: {result}");
Console.ReadKey();
}
}
Java Integration Using JNA
Implement Java interfaces to map native library functions:
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface WindowsMathLibrary extends Library {
WindowsMathLibrary INSTANCE =
(WindowsMathLibrary) Native.loadLibrary("mathlibrary.dll", WindowsMathLibrary.class);
int addValues(int first, int second);
}
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface LinuxMathLibrary extends Library {
LinuxMathLibrary INSTANCE =
(LinuxMathLibrary) Native.loadLibrary("libmathlibrary.so", LinuxMathLibrary.class);
int calculateSum(int first, int second);
}
Main application logic for cross-platform execution:
public class Application {
public static void main(String[] args) {
String platform = System.getProperty("os.name").toLowerCase();
int computationResult = 0;
if (platform.contains("windows")) {
computationResult = WindowsMathLibrary.INSTANCE.addValues(5, 6);
} else if (platform.contains("linux")) {
computationResult = LinuxMathLibrary.INSTANCE.calculateSum(5, 6);
} else {
System.out.println("Unsupported platform: " + platform);
}
System.out.println("Native function output: " + computationResult);
}
}
Include JNA dependency in project configuraton:
<dependencies>
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>5.12.1</version>
</dependency>
</dependencies>