September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -2,5 +2,7 @@ Show how to call a function in a shared library (without dynamically linking to
|
|||
|
||||
This is a special case of [[Call foreign language function|calling a foreign language function]] where the focus is close to the ABI level and not at the normal API level.
|
||||
|
||||
===Related tasks===
|
||||
|
||||
;Related task:
|
||||
* [[OpenGL]] -- OpenGL is usually maintained as a shared library.
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
' Call a dynamic library function
|
||||
PROTO j0
|
||||
bessel0 = j0(1.0)
|
||||
PRINT bessel0
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env stack
|
||||
-- stack --resolver lts-6.33 --install-ghc runghc --package unix
|
||||
|
||||
import Control.Exception ( try )
|
||||
import Foreign ( FunPtr, allocaBytes )
|
||||
import Foreign.C
|
||||
( CSize(..), CString, withCAStringLen, peekCAStringLen )
|
||||
import System.Info ( os )
|
||||
import System.IO.Error ( ioeGetErrorString )
|
||||
import System.IO.Unsafe ( unsafePerformIO )
|
||||
import System.Posix.DynamicLinker
|
||||
( RTLDFlags(RTLD_LAZY), dlsym, dlopen )
|
||||
|
||||
dlSuffix :: String
|
||||
dlSuffix = if os == "darwin" then ".dylib" else ".so"
|
||||
|
||||
type RevFun = CString -> CString -> CSize -> IO ()
|
||||
|
||||
foreign import ccall "dynamic"
|
||||
mkFun :: FunPtr RevFun -> RevFun
|
||||
|
||||
callRevFun :: RevFun -> String -> String
|
||||
callRevFun f s = unsafePerformIO $ withCAStringLen s $ \(cs, len) -> do
|
||||
allocaBytes len $ \buf -> do
|
||||
f buf cs (fromIntegral len)
|
||||
peekCAStringLen (buf, len)
|
||||
|
||||
getReverse :: IO (String -> String)
|
||||
getReverse = do
|
||||
lib <- dlopen ("libcrypto" ++ dlSuffix) [RTLD_LAZY]
|
||||
fun <- dlsym lib "BUF_reverse"
|
||||
return $ callRevFun $ mkFun fun
|
||||
|
||||
main = do
|
||||
x <- try getReverse
|
||||
let (msg, rev) =
|
||||
case x of
|
||||
Left e -> (ioeGetErrorString e ++ "; using fallback", reverse)
|
||||
Right f -> ("Using BUF_reverse from OpenSSL", f)
|
||||
putStrLn msg
|
||||
putStrLn $ rev "a man a plan a canal panama"
|
||||
|
|
@ -1,8 +1,71 @@
|
|||
public class LoadLib{
|
||||
private static native void functionInSharedLib(); //change return type or parameters as necessary
|
||||
/* TrySort.java */
|
||||
|
||||
public static void main(String[] args){
|
||||
System.loadLibrary("Path/to/library/here/lib.dll");
|
||||
functionInSharedLib();
|
||||
}
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
|
||||
public class TrySort {
|
||||
static boolean useC;
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary("TrySort");
|
||||
useC = true;
|
||||
} catch(UnsatisfiedLinkError e) {
|
||||
useC = false;
|
||||
}
|
||||
}
|
||||
|
||||
static native void sortInC(int[] ary);
|
||||
|
||||
static class IntList extends java.util.AbstractList<Integer> {
|
||||
int[] ary;
|
||||
IntList(int[] ary) { this.ary = ary; }
|
||||
public Integer get(int i) { return ary[i]; }
|
||||
public Integer set(int i, Integer j) {
|
||||
Integer o = ary[i]; ary[i] = j; return o;
|
||||
}
|
||||
public int size() { return ary.length; }
|
||||
}
|
||||
|
||||
static class ReverseAbsCmp
|
||||
implements java.util.Comparator<Integer>
|
||||
{
|
||||
public int compare(Integer pa, Integer pb) {
|
||||
/* Order from highest to lowest absolute value. */
|
||||
int a = pa > 0 ? -pa : pa;
|
||||
int b = pb > 0 ? -pb : pb;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void sortInJava(int[] ary) {
|
||||
Collections.sort(new IntList(ary), new ReverseAbsCmp());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
/* Create an array of random integers. */
|
||||
int[] ary = new int[1000000];
|
||||
Random rng = new Random();
|
||||
for (int i = 0; i < ary.length; i++)
|
||||
ary[i] = rng.nextInt();
|
||||
|
||||
/* Do the reverse sort. */
|
||||
if (useC) {
|
||||
System.out.print("Sorting in C... ");
|
||||
sortInC(ary);
|
||||
} else {
|
||||
System.out.print
|
||||
("Missing library for C! Sorting in Java... ");
|
||||
sortInJava(ary);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ary.length - 1; i++) {
|
||||
int a = ary[i];
|
||||
int b = ary[i + 1];
|
||||
if ((a > 0 ? -a : a) > (b > 0 ? -b : b)) {
|
||||
System.out.println("*BUG IN SORT*");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
System.out.println("ok");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,34 @@
|
|||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
/* TrySort.c */
|
||||
|
||||
public class LoadLibJNA{
|
||||
private interface YourSharedLibraryName extends Library{
|
||||
//put shared library functions here with no definition
|
||||
public void sharedLibraryfunction();
|
||||
}
|
||||
#include <stdlib.h>
|
||||
#include "TrySort.h"
|
||||
|
||||
public static void main(String[] args){
|
||||
YourSharedLibraryName lib = (YourSharedLibraryName)Native.loadLibrary("sharedLibrary",//as in "sharedLibrary.dll"
|
||||
YourSharedLibraryName.class);
|
||||
lib.sharedLibraryFunction();
|
||||
}
|
||||
static void fail(JNIEnv *jenv, const char *error_name) {
|
||||
jclass error_class = (*jenv)->FindClass(jenv, error_name);
|
||||
(*jenv)->ThrowNew(jenv, error_class, NULL);
|
||||
}
|
||||
|
||||
static int reverse_abs_cmp(const void *pa, const void *pb) {
|
||||
jint a = *(jint *)pa;
|
||||
jint b = *(jint *)pb;
|
||||
a = a > 0 ? -a : a;
|
||||
b = b > 0 ? -b : b;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}
|
||||
|
||||
void Java_TrySort_sortInC(JNIEnv *jenv, jclass obj, jintArray ary) {
|
||||
jint *elem, length;
|
||||
|
||||
if (ary == NULL) {
|
||||
fail(jenv, "java/lang/NullPointerException");
|
||||
return;
|
||||
}
|
||||
length = (*jenv)->GetArrayLength(jenv, ary);
|
||||
elem = (*jenv)->GetPrimitiveArrayCritical(jenv, ary, NULL);
|
||||
if (elem == NULL) {
|
||||
fail(jenv, "java/lang/OutOfMemoryError");
|
||||
return;
|
||||
}
|
||||
qsort(elem, length, sizeof(jint), reverse_abs_cmp);
|
||||
(*jenv)->ReleasePrimitiveArrayCritical(jenv, ary, elem, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# Makefile
|
||||
|
||||
# Edit the next lines to match your JDK.
|
||||
JAVA_HOME = /usr/local/jdk-1.8.0
|
||||
CPPFLAGS = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/openbsd
|
||||
JAVAC = $(JAVA_HOME)/bin/javac
|
||||
JAVAH = $(JAVA_HOME)/bin/javah
|
||||
|
||||
CC = cc
|
||||
LDFLAGS = -shared -fPIC
|
||||
LIB = libTrySort.so
|
||||
|
||||
all: TrySort.class $(LIB)
|
||||
|
||||
$(LIB): TrySort.c TrySort.h
|
||||
$(CC) $(CPPFLAGS) $(LDFLAGS) -o $@ TrySort.c
|
||||
|
||||
.SUFFIXES: .class .java .h
|
||||
.class.h:
|
||||
rm -f $@
|
||||
$(JAVAH) -jni -o $@ $(<:.class=)
|
||||
.java.class:
|
||||
$(JAVAC) $<
|
||||
|
||||
clean:
|
||||
rm -f TrySort.class TrySort?IntList.class \
|
||||
TrySort?ReverseAbsCmp.class TrySort.h $(LIB)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import com.sun.jna.Library;
|
||||
import com.sun.jna.Native;
|
||||
|
||||
public class LoadLibJNA{
|
||||
private interface YourSharedLibraryName extends Library{
|
||||
//put shared library functions here with no definition
|
||||
public void sharedLibraryfunction();
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
YourSharedLibraryName lib = (YourSharedLibraryName)Native.loadLibrary("sharedLibrary",//as in "sharedLibrary.dll"
|
||||
YourSharedLibraryName.class);
|
||||
lib.sharedLibraryFunction();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
string {libname,funcname} = iff(platform()=WINDOWS?{"user32","CharLowerA"}:{"libc","tolower"})
|
||||
atom lib = open_dll(libname)
|
||||
integer func = define_c_func(lib,funcname,{C_INT},C_INT)
|
||||
if func=-1 then
|
||||
?{{lower('A')}}
|
||||
else
|
||||
?c_func(func,{'A'}) -- ('A'==65)
|
||||
end if
|
||||
|
|
@ -1,11 +1,20 @@
|
|||
require 'dl/import'
|
||||
require 'fiddle/import'
|
||||
|
||||
FakeImgLib = DL.dlopen("/path/to/fakeimg.so")
|
||||
|
||||
module FakeImage
|
||||
def self.openimage filename
|
||||
FakeImgLib["openimage", "IS"].call(filename)[0]
|
||||
module FakeImgLib
|
||||
extend Fiddle::Importer
|
||||
begin
|
||||
dlload './fakeimglib.so'
|
||||
extern 'int openimage(const char *)'
|
||||
rescue Fiddle::DLError
|
||||
# Either fakeimglib or openimage() is missing.
|
||||
@@handle = -1
|
||||
def openimage(path)
|
||||
$stderr.puts "internal openimage opens #{path}\n"
|
||||
@@handle += 1
|
||||
end
|
||||
module_function :openimage
|
||||
end
|
||||
end
|
||||
|
||||
handle = FakeImage.openimage("path/to/image")
|
||||
handle = FakeImgLib.openimage("path/to/image")
|
||||
puts "opened with handle #{handle}"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,72 @@
|
|||
require 'ffi'
|
||||
module FakeImgLib
|
||||
extend FFI::Library
|
||||
ffi_lib "path/to/fakeimglib.so"
|
||||
attach_function :openimage, [:string], :int
|
||||
# This script shows the width x height of some images.
|
||||
# Example:
|
||||
# $ ruby imsize.rb dwarf-vs-elf.png swedish-chef.jpg
|
||||
# dwarf-vs-elf.png: 242x176
|
||||
# swedish-chef.jpg: 256x256
|
||||
|
||||
begin
|
||||
require 'rmagick'
|
||||
lib = :rmagick
|
||||
rescue LoadError
|
||||
# Missing rmagick. Try ffi.
|
||||
begin
|
||||
require 'ffi'
|
||||
module F
|
||||
extend FFI::Library
|
||||
ffi_lib 'MagickWand-6.Q16'
|
||||
attach_function :DestroyMagickWand, [:pointer], :pointer
|
||||
attach_function :MagickGetImageHeight, [:pointer], :size_t
|
||||
attach_function :MagickGetImageWidth, [:pointer], :size_t
|
||||
attach_function :MagickPingImage, [:pointer, :string], :bool
|
||||
attach_function :MagickWandGenesis, [], :void
|
||||
attach_function :NewMagickWand, [], :pointer
|
||||
end
|
||||
lib = :ffi
|
||||
rescue LoadError
|
||||
# Missing ffi, MagickWand lib, or function in lib.
|
||||
end
|
||||
end
|
||||
|
||||
handle = FakeImgLib.openimage("path/to/image")
|
||||
case lib
|
||||
when :rmagick
|
||||
# Returns [width, height] of an image file.
|
||||
def size(path)
|
||||
img = Magick::Image.ping(path).first
|
||||
[img.columns, img.rows]
|
||||
end
|
||||
when :ffi
|
||||
F.MagickWandGenesis()
|
||||
def size(path)
|
||||
wand = F.NewMagickWand()
|
||||
F.MagickPingImage(wand, path) or fail 'problem reading image'
|
||||
[F.MagickGetImageWidth(wand), F.MagickGetImageHeight(wand)]
|
||||
ensure
|
||||
F.DestroyMagickWand(wand) if wand
|
||||
end
|
||||
else
|
||||
PngSignature = "\x89PNG\r\n\x1A\n".force_encoding('binary')
|
||||
def size(path)
|
||||
File.open(path, 'rb') do |file|
|
||||
# Only works with PNG: https://www.w3.org/TR/PNG/
|
||||
# Reads [width, height] from IDHR chunk.
|
||||
# Checks height != nil, but doesn't check CRC of chunk.
|
||||
sig, width, height = file.read(24).unpack('a8@16NN')
|
||||
sig == PngSignature and height or fail 'not a PNG image'
|
||||
[width, height]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Show the size of each image in ARGV.
|
||||
status = true
|
||||
ARGV.empty? and (warn "usage: $0 file..."; exit false)
|
||||
ARGV.each do |path|
|
||||
begin
|
||||
r, c = size(path)
|
||||
puts "#{path}: #{r}x#{c}"
|
||||
rescue
|
||||
status = false
|
||||
puts "#{path}: #$!"
|
||||
end
|
||||
end
|
||||
exit status
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
#![allow(unused_unsafe)]
|
||||
extern crate libc;
|
||||
|
||||
use std::io::{self,Write};
|
||||
use std::{mem,ffi,process};
|
||||
|
||||
use libc::{c_double, RTLD_NOW};
|
||||
|
||||
// Small macro which wraps turning a string-literal into a c-string.
|
||||
// This is always safe to call, and the resulting pointer has 'static lifetime
|
||||
macro_rules! to_cstr {
|
||||
($s:expr) => {unsafe {ffi::CStr::from_bytes_with_nul_unchecked(concat!($s, "\0").as_bytes()).as_ptr()}}
|
||||
}
|
||||
|
||||
macro_rules! from_cstr {
|
||||
($p:expr) => {ffi::CStr::from_ptr($p).to_string_lossy().as_ref() }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let handle = libc::dlopen(to_cstr!("libm.so.6"), RTLD_NOW);
|
||||
|
||||
if handle.is_null() {
|
||||
writeln!(&mut io::stderr(), "{}", from_cstr!(libc::dlerror())).unwrap();
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let extern_cos = libc::dlsym(handle, to_cstr!("cos"))
|
||||
.as_ref()
|
||||
.map(mem::transmute::<_,fn (c_double) -> c_double)
|
||||
.unwrap_or(builtin_cos);
|
||||
println!("{}", extern_cos(4.0));
|
||||
}
|
||||
}
|
||||
|
||||
fn builtin_cos(x: c_double) -> c_double {
|
||||
x.cos()
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
var BN=Import("zklBigNum");
|
||||
BN(1)+2 //--> BN(3)
|
||||
Loading…
Add table
Add a link
Reference in a new issue