--- name: polyglot-integration description: Integrate multiple programming languages using FFI, native bindings, gRPC, or language bridges. Use when combining strengths of different languages or integrating legacy systems. --- # Polyglot Integration ## Overview Integrate code written in different programming languages to leverage their unique strengths and ecosystems. ## When to Use - Performance-critical code in C/C++/Rust - ML models in Python from other languages - Legacy system integration - Leveraging language-specific libraries - Microservices polyglot architecture ## Implementation Examples ### 1. **Node.js Native Addons (C++)** ```cpp // addon.cc #include namespace demo { using v8::FunctionCallbackInfo; using v8::Isolate; using v8::Local; using v8::Object; using v8::String; using v8::Value; using v8::Number; void Add(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); if (args.Length() < 2) { isolate->ThrowException(v8::Exception::TypeError( String::NewFromUtf8(isolate, "Wrong number of arguments"))); return; } if (!args[0]->IsNumber() || !args[1]->IsNumber()) { isolate->ThrowException(v8::Exception::TypeError( String::NewFromUtf8(isolate, "Arguments must be numbers"))); return; } double value = args[0]->NumberValue() + args[1]->NumberValue(); Local num = Number::New(isolate, value); args.GetReturnValue().Set(num); } void Initialize(Local exports) { NODE_SET_METHOD(exports, "add", Add); } NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize) } ``` ```javascript // Usage in Node.js const addon = require('./build/Release/addon'); console.log(addon.add(3, 5)); // 8 ``` ### 2. **Python from Node.js** ```typescript // Using child_process import { spawn } from 'child_process'; function callPython(script: string, args: any[] = []): Promise { return new Promise((resolve, reject) => { const python = spawn('python3', [script, ...args.map(String)]); let stdout = ''; let stderr = ''; python.stdout.on('data', (data) => { stdout += data.toString(); }); python.stderr.on('data', (data) => { stderr += data.toString(); }); python.on('close', (code) => { if (code !== 0) { reject(new Error(stderr)); } else { try { resolve(JSON.parse(stdout)); } catch (error) { resolve(stdout); } } }); }); } // Usage const result = await callPython('./ml_model.py', [100, 200]); console.log('Python result:', result); ``` ```python # ml_model.py import sys import json def predict(x, y): # ML model logic return x * 2 + y if __name__ == '__main__': x = int(sys.argv[1]) y = int(sys.argv[2]) result = predict(x, y) print(json.dumps({'prediction': result})) ``` ### 3. **Rust from Python (PyO3)** ```rust // lib.rs use pyo3::prelude::*; #[pyfunction] fn fibonacci(n: u64) -> PyResult { let mut a = 0; let mut b = 1; for _ in 0..n { let temp = a; a = b; b = temp + b; } Ok(a) } #[pyfunction] fn process_large_array(arr: Vec) -> PyResult { Ok(arr.iter().sum()) } #[pymodule] fn rust_extension(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(fibonacci, m)?)?; m.add_function(wrap_pyfunction!(process_large_array, m)?)?; Ok(()) } ``` ```python # Usage in Python import rust_extension result = rust_extension.fibonacci(100) print(f"Fibonacci: {result}") arr = list(range(1000000)) total = rust_extension.process_large_array(arr) print(f"Sum: {total}") ``` ### 4. **gRPC Polyglot Communication** ```protobuf // service.proto syntax = "proto3"; service Calculator { rpc Add (NumberPair) returns (Result); rpc Multiply (NumberPair) returns (Result); } message NumberPair { double a = 1; double b = 2; } message Result { double value = 1; } ``` ```python # Python gRPC Server import grpc from concurrent import futures import service_pb2 import service_pb2_grpc class Calculator(service_pb2_grpc.CalculatorServicer): def Add(self, request, context): return service_pb2.Result(value=request.a + request.b) def Multiply(self, request, context): return service_pb2.Result(value=request.a * request.b) def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) service_pb2_grpc.add_CalculatorServicer_to_server(Calculator(), server) server.add_insecure_port('[::]:50051') server.start() server.wait_for_termination() if __name__ == '__main__': serve() ``` ```typescript // Node.js gRPC Client import * as grpc from '@grpc/grpc-js'; import * as protoLoader from '@grpc/proto-loader'; const packageDefinition = protoLoader.loadSync('service.proto'); const proto = grpc.loadPackageDefinition(packageDefinition); const client = new proto.Calculator( 'localhost:50051', grpc.credentials.createInsecure() ); client.Add({ a: 10, b: 20 }, (error, response) => { if (error) { console.error(error); } else { console.log('Result:', response.value); } }); ``` ### 5. **Java from Python (Py4J)** ```java // JavaApp.java public class JavaApp { public int add(int a, int b) { return a + b; } public String processData(String data) { return data.toUpperCase(); } public static void main(String[] args) { JavaApp app = new JavaApp(); GatewayServer server = new GatewayServer(app); server.start(); } } ``` ```python # Python client from py4j.java_gateway import JavaGateway gateway = JavaGateway() app = gateway.entry_point result = app.add(10, 20) print(f"Result: {result}") processed = app.processData("hello world") print(f"Processed: {processed}") ``` ## Best Practices ### ✅ DO - Use appropriate IPC mechanism - Handle serialization carefully - Implement proper error handling - Consider performance overhead - Use type-safe interfaces - Document integration points ### ❌ DON'T - Pass complex objects across boundaries - Ignore memory management - Skip error handling - Use blocking calls in async code ## Integration Methods | Method | Use Case | Overhead | |--------|----------|----------| | **Native Bindings** | Performance-critical code | Low | | **IPC/Pipes** | Separate processes | Medium | | **gRPC** | Microservices | Medium | | **HTTP/REST** | Loose coupling | High | | **Message Queue** | Async processing | Medium | ## Resources - [Node.js C++ Addons](https://nodejs.org/api/addons.html) - [PyO3](https://pyo3.rs/) - [gRPC](https://grpc.io/) - [Py4J](https://www.py4j.org/)