| Crates.io | cblas-inject |
| lib.rs | cblas-inject |
| version | 0.1.0 |
| created_at | 2026-01-22 22:59:08.512163+00 |
| updated_at | 2026-01-22 22:59:08.512163+00 |
| description | CBLAS compatible interface backed by runtime-registered Fortran BLAS function pointers |
| homepage | |
| repository | https://github.com/shinaoka/cblas-inject |
| max_upload_size | |
| id | 2062852 |
| size | 645,577 |
CBLAS compatible interface backed by Fortran BLAS function pointers.
This crate provides CBLAS-style functions (with row-major support) that internally call Fortran BLAS functions via runtime-registered function pointers. This is useful for integrating Rust code with:
scipy.linalg.cython_blas.__pyx_capi__LinearAlgebra.BLAS.lbt_get_forward()OnceLock for minimal overhead (~0.5ns per call)ilp64 feature for 64-bit integersuse cblas_inject::{
register_dgemm, cblas_dgemm,
CblasRowMajor, CblasNoTrans,
};
fn main() {
// Register Fortran dgemm pointer (obtained from Python/Julia)
unsafe {
register_dgemm(dgemm_ptr);
}
// Use CBLAS-style interface
let m = 2;
let n = 3;
let k = 4;
let alpha = 1.0;
let beta = 0.0;
let a: Vec<f64> = vec![/* m x k matrix, row-major */];
let b: Vec<f64> = vec![/* k x n matrix, row-major */];
let mut c: Vec<f64> = vec![0.0; m * n];
unsafe {
cblas_dgemm(
CblasRowMajor,
CblasNoTrans,
CblasNoTrans,
m as i32, n as i32, k as i32,
alpha,
a.as_ptr(), k as i32, // lda = k for row-major NoTrans
b.as_ptr(), n as i32, // ldb = n for row-major NoTrans
beta,
c.as_mut_ptr(), n as i32, // ldc = n for row-major
);
}
}
See examples/julia/dgemm_example.jl for a complete working example.
using LinearAlgebra, Libdl
# Build with ILP64 for modern Julia: cargo build --release --features ilp64
lib = dlopen("path/to/libcblas_inject.dylib")
# Get dgemm_ pointer from libblastrampoline
dgemm_ptr = LinearAlgebra.BLAS.lbt_get_forward("dgemm_", :ilp64)
# Register with cblas-inject
register_dgemm = dlsym(lib, :register_dgemm)
ccall(register_dgemm, Cvoid, (Ptr{Cvoid},), dgemm_ptr)
# Now use cblas_dgemm
cblas_dgemm = dlsym(lib, :cblas_dgemm)
# ... call cblas_dgemm via ccall
See examples/python/dgemm_example.py for a complete working example.
import ctypes
import scipy.linalg.cython_blas as blas
# Build: cargo build --release
lib = ctypes.CDLL("path/to/libcblas_inject.dylib")
# Extract dgemm pointer from scipy's PyCapsule
capsule = blas.__pyx_capi__['dgemm']
ctypes.pythonapi.PyCapsule_GetName.restype = ctypes.c_char_p
ctypes.pythonapi.PyCapsule_GetName.argtypes = [ctypes.py_object]
capsule_name = ctypes.pythonapi.PyCapsule_GetName(capsule)
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
dgemm_ptr = ctypes.pythonapi.PyCapsule_GetPointer(capsule, capsule_name)
# Register with cblas-inject
lib.register_dgemm(dgemm_ptr)
# Now use cblas_dgemm
# ... call lib.cblas_dgemm with ctypes
For BLAS operations (GEMM, etc.), row-major data is handled via argument swapping without memory copy, following the same approach as OpenBLAS:
C = A × B (row-major)
⟺ C^T = B^T × A^T (column-major)
Fortran complex functions (cdotu, cdotc, zdotu, zdotc) have two calling conventions:
Set the convention before registering complex dot product functions:
use cblas_inject::{set_complex_return_style, ComplexReturnStyle};
unsafe {
set_complex_return_style(ComplexReturnStyle::ReturnValue);
register_zdotc(zdotc_ptr);
}
See examples/julia/zdotc_example.jl and examples/python/zdotc_example.py for complete examples.
All functions from cblas-sys are implemented:
sdot, ddot, cdotu_sub, cdotc_sub, zdotu_sub, zdotc_sub, sdsdot, dsdotsnrm2, dnrm2, scnrm2, dznrm2sasum, dasum, scasum, dzasumisamax, idamax, icamax, izamaxsswap, dswap, cswap, zswap, scopy, dcopy, ccopy, zcopy, saxpy, daxpy, caxpy, zaxpysscal, dscal, cscal, zscal, csscal, zdscalsrot, drot, srotg, drotg, srotm, drotm, srotmg, drotmgscabs1, dcabs1sgemv, dgemv, cgemv, zgemv, sgbmv, dgbmv, cgbmv, zgbmvstrmv, dtrmv, ctrmv, ztrmv, stbmv, dtbmv, ctbmv, ztbmv, stpmv, dtpmv, ctpmv, ztpmvstrsv, dtrsv, ctrsv, ztrsv, stbsv, dtbsv, ctbsv, ztbsv, stpsv, dtpsv, ctpsv, ztpsvssymv, dsymv, chemv, zhemv, ssbmv, dsbmv, chbmv, zhbmv, sspmv, dspmv, chpmv, zhpmvsger, dger, cgeru, cgerc, zgeru, zgerc, ssyr, dsyr, cher, zher, sspr, dspr, chpr, zhpr, ssyr2, dsyr2, cher2, zher2, sspr2, dspr2, chpr2, zhpr2sgemm, dgemm, cgemm, zgemmssymm, dsymm, csymm, zsymm, chemm, zhemmssyrk, dsyrk, csyrk, zsyrk, cherk, zherkssyr2k, dsyr2k, csyr2k, zsyr2k, cher2k, zher2kstrmm, dtrmm, ctrmm, ztrmmstrsm, dtrsm, ctrsm, ztrsmcblas_xerbla: Error handler (simplified non-variadic version)MIT OR Apache-2.0. This project also includes portions derived from OpenBLAS
under the BSD-3-Clause license. See THIRD_PARTY_NOTICES.md.
The row-major conversion logic is based on OpenBLAS (BSD-3-Clause license).