Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Use_another_language_to_call_a_function
|
||||
note: Programming environment operations
|
||||
24
Task/Use-another-language-to-call-a-function/00-TASK.txt
Normal file
24
Task/Use-another-language-to-call-a-function/00-TASK.txt
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
This task is inverse to the task [[Call foreign language function]]. Consider the following [[C]] program:
|
||||
<syntaxhighlight lang="c">#include <stdio.h>
|
||||
|
||||
extern int Query (char * Data, size_t * Length);
|
||||
|
||||
int main (int argc, char * argv [])
|
||||
{
|
||||
char Buffer [1024];
|
||||
size_t Size = sizeof (Buffer);
|
||||
|
||||
if (0 == Query (Buffer, &Size))
|
||||
{
|
||||
printf ("failed to call Query\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char * Ptr = Buffer;
|
||||
while (Size-- > 0) putchar (*Ptr++);
|
||||
putchar ('\n');
|
||||
}
|
||||
}</syntaxhighlight>
|
||||
|
||||
Implement the missing <code>Query</code> function in your language, and let this C program call it. The function should place the string ''<tt style="margin:0 0.5em">Here am I</tt>'' into the buffer which is passed to it as the parameter <code>Data</code>. The buffer size in bytes is passed as the parameter <code>Length</code>. When there is no room in the buffer, <code>Query</code> shall return 0. Otherwise it overwrites the beginning of <code>Buffer</code>, sets the number of overwritten bytes into <code>Length</code> and returns 1.
|
||||
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
with Interfaces.C; use Interfaces.C;
|
||||
with Interfaces.C.Strings; use Interfaces.C.Strings;
|
||||
|
||||
package Exported is
|
||||
function Query (Data : chars_ptr; Size : access size_t)
|
||||
return int;
|
||||
pragma Export (C, Query, "Query");
|
||||
end Exported;
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package body Exported is
|
||||
function Query (Data : chars_ptr; Size : access size_t)
|
||||
return int is
|
||||
Result : char_array := "Here am I";
|
||||
begin
|
||||
if Size.all < Result'Length then
|
||||
return 0;
|
||||
else
|
||||
Update (Data, 0, Result);
|
||||
Size.all := Result'Length;
|
||||
return 1;
|
||||
end if;
|
||||
end Query;
|
||||
end Exported;
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
gcc -c main.c
|
||||
gnatmake -c exported.adb
|
||||
gnatbind -n exported.ali
|
||||
gnatlink exported.ali main.o -o main
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
; Example: The following is a working script that displays a summary of all top-level windows.
|
||||
|
||||
; For performance and memory conservation, call RegisterCallback() only once for a given callback:
|
||||
if not EnumAddress ; Fast-mode is okay because it will be called only from this thread:
|
||||
EnumAddress := RegisterCallback("EnumWindowsProc", "Fast")
|
||||
|
||||
DetectHiddenWindows On ; Due to fast-mode, this setting will go into effect for the callback too.
|
||||
|
||||
; Pass control to EnumWindows(), which calls the callback repeatedly:
|
||||
DllCall("EnumWindows", UInt, EnumAddress, UInt, 0)
|
||||
MsgBox %Output% ; Display the information accumulated by the callback.
|
||||
|
||||
EnumWindowsProc(hwnd, lParam)
|
||||
{
|
||||
global Output
|
||||
WinGetTitle, title, ahk_id %hwnd%
|
||||
WinGetClass, class, ahk_id %hwnd%
|
||||
if title
|
||||
Output .= "HWND: " . hwnd . "`tTitle: " . title . "`tClass: " . class . "`n"
|
||||
return true ; Tell EnumWindows() to continue until all windows have been enumerated.
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#include <string>
|
||||
using std::string;
|
||||
|
||||
// C++ functions with extern "C" can get called from C.
|
||||
extern "C" int
|
||||
Query (char *Data, size_t *Length)
|
||||
{
|
||||
const string Message = "Here am I";
|
||||
|
||||
// Check that Message fits in Data.
|
||||
if (*Length < Message.length())
|
||||
return false; // C++ converts bool to int.
|
||||
|
||||
*Length = Message.length();
|
||||
Message.copy(Data, *Length);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
$ gcc -c main.c
|
||||
$ g++ -c query.cpp
|
||||
$ g++ -o main main.o query.o
|
||||
$ ./main
|
||||
Here am I
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#if 0
|
||||
I rewrote the driver according to good sense, my style,
|
||||
and discussion.
|
||||
|
||||
This is file main.c on Autumn 2011 ubuntu linux release.
|
||||
The emacs compile command output:
|
||||
|
||||
-*- mode: compilation; default-directory: "/tmp/" -*-
|
||||
Compilation started at Mon Mar 12 20:25:27
|
||||
|
||||
make -k CFLAGS=-Wall main.o
|
||||
cc -Wall -c -o main.o main.c
|
||||
|
||||
Compilation finished at Mon Mar 12 20:25:27
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern int Query(char *Data, unsigned *Length);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char Buffer[1024], *pc;
|
||||
unsigned Size = sizeof(Buffer);
|
||||
if (!Query(Buffer, &Size))
|
||||
fputs("failed to call Query", stdout);
|
||||
else
|
||||
for (pc = Buffer; Size--; ++pc)
|
||||
putchar(*pc);
|
||||
putchar('\n');
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#if 0
|
||||
This is file query.c
|
||||
|
||||
-*- mode: compilation; default-directory: "/tmp/" -*-
|
||||
Compilation started at Mon Mar 12 20:36:25
|
||||
|
||||
make -k CFLAGS=-Wall query.o
|
||||
cc -Wall -c -o query.o query.c
|
||||
|
||||
Compilation finished at Mon Mar 12 20:36:26
|
||||
#endif
|
||||
|
||||
#include<string.h>
|
||||
|
||||
int Query(char *Data, unsigned *Length) {
|
||||
const char *message = "Here am I";
|
||||
unsigned n = strlen(message);
|
||||
if (n <= *Length)
|
||||
return strncpy(Data, message, (size_t)n), *Length = n, 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
$ gcc main.c query.o -o main && ./main
|
||||
Here am I
|
||||
$
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
identification division.
|
||||
program-id. Query.
|
||||
|
||||
environment division.
|
||||
configuration section.
|
||||
special-names.
|
||||
call-convention 0 is extern.
|
||||
|
||||
repository.
|
||||
function all intrinsic.
|
||||
|
||||
data division.
|
||||
working-storage section.
|
||||
01 query-result.
|
||||
05 filler value "Here I am".
|
||||
|
||||
linkage section.
|
||||
01 data-reference.
|
||||
05 data-buffer pic x occurs 0 to 8192 times
|
||||
depending on length-reference.
|
||||
01 length-reference usage binary-long.
|
||||
|
||||
procedure division extern using data-reference length-reference.
|
||||
|
||||
if length(query-result) less than or equal to length-reference
|
||||
and length-reference less than 8193 then
|
||||
move query-result to data-reference
|
||||
move length(query-result) to length-reference
|
||||
move 1 to return-code
|
||||
end-if
|
||||
|
||||
goback.
|
||||
end program Query.
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import core.stdc.string;
|
||||
|
||||
extern(C) bool query(char *data, size_t *length) pure nothrow {
|
||||
immutable text = "Here am I";
|
||||
|
||||
if (*length < text.length) {
|
||||
*length = 0; // Also clears length.
|
||||
return false;
|
||||
} else {
|
||||
memcpy(data, text.ptr, text.length);
|
||||
*length = text.length;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
extern bool query(char *data, size_t *length);
|
||||
|
||||
int main() {
|
||||
char buffer[1024];
|
||||
size_t size = sizeof(buffer);
|
||||
|
||||
if (query(buffer, &size))
|
||||
printf("%.*s\n", size, buffer);
|
||||
else
|
||||
puts("The call to query has failed.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
function Query(Buffer: PChar; var Size: Int64): LongBool;
|
||||
const
|
||||
Text = 'Hello World!';
|
||||
begin
|
||||
If not Assigned(Buffer) Then
|
||||
begin
|
||||
Size := 0;
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
If Size < Length(Text) Then
|
||||
begin
|
||||
Size := 0;
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Size := Length(Text);
|
||||
Move(Text[1], Buffer^, Size);
|
||||
Result := True;
|
||||
end;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
!-----------------------------------------------------------------------
|
||||
!Function
|
||||
!-----------------------------------------------------------------------
|
||||
function fortran_query(data, length) result(answer) bind(c, name='Query')
|
||||
use, intrinsic :: iso_c_binding, only: c_char, c_int, c_size_t, c_null_char
|
||||
implicit none
|
||||
character(len=1,kind=c_char), dimension(length), intent(inout) :: data
|
||||
integer(c_size_t), intent(inout) :: length
|
||||
integer(c_int) :: answer
|
||||
answer = 0
|
||||
if(length<10) return
|
||||
data = transfer("Here I am"//c_null_char, data)
|
||||
length = 10_c_size_t
|
||||
answer = 1
|
||||
end function fortran_query
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#include <stdio.h>
|
||||
#include "_cgo_export.h"
|
||||
|
||||
void Run()
|
||||
{
|
||||
char Buffer [1024];
|
||||
size_t Size = sizeof (Buffer);
|
||||
|
||||
if (0 == Query (Buffer, &Size))
|
||||
...
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package main
|
||||
|
||||
// #include <stdlib.h>
|
||||
// extern void Run();
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func main() {
|
||||
C.Run()
|
||||
}
|
||||
|
||||
const msg = "Here am I"
|
||||
|
||||
//export Query
|
||||
func Query(cbuf *C.char, csiz *C.size_t) C.int {
|
||||
if int(*csiz) <= len(msg) {
|
||||
return 0
|
||||
}
|
||||
pbuf := uintptr(unsafe.Pointer(cbuf))
|
||||
for i := 0; i < len(msg); i++ {
|
||||
*((*byte)(unsafe.Pointer(pbuf))) = msg[i]
|
||||
pbuf++
|
||||
}
|
||||
*((*byte)(unsafe.Pointer(pbuf))) = 0
|
||||
*csiz = C.size_t(len(msg) + 1)
|
||||
return 1
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// This buildmode requires the package to be main
|
||||
package main
|
||||
|
||||
// Import C so we can export the function to C and use C types
|
||||
|
||||
//#include <stdlib.h> // for size_t
|
||||
import "C"
|
||||
|
||||
// Import reflect and unsafe so we can wrap the C array in a Go slice
|
||||
import "reflect"
|
||||
import "unsafe"
|
||||
|
||||
// This buildmode also requires a main function, but it is never actually called
|
||||
func main() {}
|
||||
|
||||
// The message to copy into the buffer
|
||||
const msg = "Here am I"
|
||||
|
||||
// Here we declare the Query function using C types and export it to C
|
||||
|
||||
//export Query
|
||||
func Query(buffer *C.char, length *C.size_t) C.int {
|
||||
// Check there is enough space in the buffer
|
||||
if int(*length) < len(msg) {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Wrap the buffer in a slice to make it easier to copy into
|
||||
sliceHeader := reflect.SliceHeader {
|
||||
Data: uintptr(unsafe.Pointer(buffer)),
|
||||
Len: len(msg),
|
||||
Cap: len(msg),
|
||||
}
|
||||
bufferSlice := *(*[]byte)(unsafe.Pointer(&sliceHeader))
|
||||
|
||||
// Iterate through the message and copy it to the buffer, byte by byte
|
||||
for i:=0;i<len(msg);i++ {
|
||||
bufferSlice[i] = msg[i]
|
||||
}
|
||||
|
||||
// Set length to the amount of bytes we copied
|
||||
(*length) = C.size_t(len(msg))
|
||||
|
||||
return 1
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#ifdef __GLASGOW_HASKELL__
|
||||
#include "Called_stub.h"
|
||||
extern void __stginit_Called(void);
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <HsFFI.h>
|
||||
|
||||
int main (int argc, char * argv [])
|
||||
{
|
||||
char Buffer [1024];
|
||||
size_t Size = sizeof (Buffer);
|
||||
|
||||
hs_init(&argc, &argv);
|
||||
#ifdef __GLASGOW_HASKELL__
|
||||
hs_add_root(__stginit_Called);
|
||||
#endif
|
||||
|
||||
if (0 == query_hs (Buffer, &Size))
|
||||
{
|
||||
printf ("failed to call Query\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char * Ptr = Buffer;
|
||||
while (Size-- > 0) putchar (*Ptr++);
|
||||
putchar ('\n');
|
||||
}
|
||||
|
||||
hs_exit();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||
|
||||
module Called where
|
||||
|
||||
import Foreign
|
||||
import Foreign.C.String (CString, withCStringLen)
|
||||
import Foreign.C.Types
|
||||
|
||||
-- place a string into the buffer pointed to by ptrBuff (with size
|
||||
-- pointed to by ptrSize). If successful, sets number of overwritten
|
||||
-- bytes in ptrSize and returns 1, otherwise, it does nothing and
|
||||
-- returns 0
|
||||
query_hs :: CString -> Ptr CSize -> IO CInt
|
||||
query_hs ptrBuff ptrSize = withCStringLen "Here I am"
|
||||
(\(str, len) -> do
|
||||
buffSize <- peek ptrSize
|
||||
if sizeOf str > (fromIntegral buffSize)
|
||||
then do
|
||||
poke ptrSize 0
|
||||
return 0
|
||||
else do
|
||||
poke ptrSize (fromIntegral len)
|
||||
copyArray ptrBuff str len
|
||||
return 1)
|
||||
|
||||
foreign export ccall query_hs :: CString -> Ptr CSize -> IO CInt
|
||||
|
|
@ -0,0 +1 @@
|
|||
ghc -c -O Called.hs
|
||||
|
|
@ -0,0 +1 @@
|
|||
ghc -optc-O calling.c Called.o Called_stub.o -o calling
|
||||
|
|
@ -0,0 +1 @@
|
|||
untyped __call__("functionName", args);
|
||||
|
|
@ -0,0 +1 @@
|
|||
query=:3 :'0&#^:(y < #)''Here am I'''
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
|
||||
int Query(char*,unsigned*);
|
||||
|
||||
int main(int argc,char*argv[]) {
|
||||
char Buffer[1024], *pc;
|
||||
unsigned Size = (unsigned)sizeof(Buffer);
|
||||
if (!Query(Buffer,&Size))
|
||||
fputs("Failed to call Query",stdout);
|
||||
else
|
||||
for (pc = Buffer; Size--; ++pc)
|
||||
putchar(*pc);
|
||||
putchar('\n');
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// J Front End Example
|
||||
// define _WIN32 for Windows, __MACH__ for MAC, J64 for 64-bit
|
||||
// JE is loaded from current working directory
|
||||
|
||||
//make jfex && LD_LIBRARY_PATH=/usr/local/j64-701/bin ./jfex
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#define GETPROCADDRESS(h,p) GetProcAddress(h,p)
|
||||
#define JDLLNAME "\\j.dll"
|
||||
#else
|
||||
#define _stdcall
|
||||
#include <dlfcn.h>
|
||||
#define GETPROCADDRESS(h,p) dlsym(h,p)
|
||||
#ifdef __MACH__
|
||||
#define JDLLNAME "/libj.dylib"
|
||||
#else
|
||||
#define JDLLNAME "/libj.so"
|
||||
#endif
|
||||
#define _getcwd getcwd
|
||||
#endif
|
||||
|
||||
#include<stdio.h>
|
||||
#include<signal.h>
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
#include"jfex.h"
|
||||
#include"jlib.h"
|
||||
|
||||
static JDoType jdo;
|
||||
static JFreeType jfree;
|
||||
static JgaType jga;
|
||||
static JGetLocaleType jgetlocale;
|
||||
|
||||
static J jt;
|
||||
static void* hjdll;
|
||||
|
||||
static char **adadbreak;
|
||||
static void sigint(int k){**adadbreak+=1;signal(SIGINT,sigint);}
|
||||
static char input[1000];
|
||||
|
||||
// J calls for input (debug suspension and 1!:1[1) and we call for input
|
||||
char* _stdcall Jinput(J jt,char* prompt)
|
||||
{
|
||||
fputs(prompt,stdout);
|
||||
if(fgets(input, sizeof(input), stdin))
|
||||
{
|
||||
fputs("\n",stdout);
|
||||
**adadbreak+=1;
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
static char*buffer = NULL; /**************************************/
|
||||
static unsigned length = 0; /**************************************/
|
||||
static int Jouts = 0; /**************************************/
|
||||
|
||||
// J calls for output
|
||||
#define LINEFEED 10 /**************************************/
|
||||
void _stdcall Joutput(J jt,int type, char* s) /********************/
|
||||
{
|
||||
size_t L;
|
||||
if(MTYOEXIT==type) exit((int)(I)s);
|
||||
L = strlen(s);
|
||||
L -= (L && (LINEFEED==s[L-1])); /* CRLF not handled. */
|
||||
if (L && (!Jouts)) {
|
||||
length = L;
|
||||
strncpy(buffer,s,L);
|
||||
Jouts = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int Query(char*Data,unsigned*Length)
|
||||
{
|
||||
void* callbacks[] = {Joutput,NULL,Jinput,0,(void*)SMCON};
|
||||
char pathdll[1000];
|
||||
_getcwd(pathdll,sizeof(pathdll));
|
||||
strcat(pathdll,JDLLNAME);
|
||||
#ifdef _WIN32
|
||||
hjdll=LoadLibraryA(pathdll);
|
||||
#else
|
||||
hjdll=dlopen(pathdll,RTLD_LAZY);
|
||||
if (NULL == hjdll)
|
||||
hjdll=dlopen(JDLLNAME+1,RTLD_LAZY); /* use LD_LIBRARY_PATH */
|
||||
#endif
|
||||
if(NULL == hjdll)
|
||||
{
|
||||
fprintf(stderr,"Unix use: $ LD_LIBRARY_PATH=path/to/libj.so %s\n","programName");//*argv);
|
||||
fputs("Load library failed: ",stderr);
|
||||
fputs(pathdll,stderr);
|
||||
fputs("\n",stderr);
|
||||
return 0; // load library failed
|
||||
}
|
||||
jt=((JInitType)GETPROCADDRESS(hjdll,"JInit"))();
|
||||
if(!jt) return 0; // JE init failed
|
||||
((JSMType)GETPROCADDRESS(hjdll,"JSM"))(jt,callbacks);
|
||||
jdo=(JDoType)GETPROCADDRESS(hjdll,"JDo");
|
||||
jfree=(JFreeType)GETPROCADDRESS(hjdll,"JFree");
|
||||
jga=(JgaType)GETPROCADDRESS(hjdll,"Jga");
|
||||
jgetlocale=(JGetLocaleType)GETPROCADDRESS(hjdll,"JGetLocale");
|
||||
adadbreak=(char**)jt; // first address in jt is address of breakdata
|
||||
signal(SIGINT,sigint);
|
||||
{
|
||||
char input[999];
|
||||
//memset(input,0,sizeof input);
|
||||
buffer = Data;
|
||||
sprintf(input,"query %u [ 0!:110<'rc_embed.ijs'\n",*Length); /***deceptive input routine, a hard coded string*********/
|
||||
jdo(jt,input);
|
||||
if (!Jouts)
|
||||
return 0;
|
||||
*Length = length;
|
||||
}
|
||||
jfree(jt);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# jfe makefile info
|
||||
# customize to create makefile suitable for your platform
|
||||
# 32bit builds on 64bit systems require -m32 in CFLAGS and FLAGS
|
||||
# Unix requires -ldl in FLAGS and Windows does not
|
||||
|
||||
CPPFLAGS= -I/usr/local/j64-602/system/examples/jfe
|
||||
CFLAGS= -O0 -g
|
||||
LOADLIBES= -ldl
|
||||
|
||||
main: main.o Query.o
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
$ make main && LD_LIBRARY_PATH=~/Downloads/jgplsrc/j/bin ./main
|
||||
Here am I
|
||||
$
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/* Query.java */
|
||||
public class Query {
|
||||
public static boolean call(byte[] data, int[] length)
|
||||
throws java.io.UnsupportedEncodingException
|
||||
{
|
||||
String message = "Here am I";
|
||||
byte[] mb = message.getBytes("utf-8");
|
||||
if (length[0] < mb.length)
|
||||
return false;
|
||||
length[0] = mb.length;
|
||||
System.arraycopy(mb, 0, data, 0, mb.length);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/* query-jni.c */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
|
||||
static JavaVM *jvm = NULL;
|
||||
static JNIEnv *jenv = NULL;
|
||||
|
||||
static void die(const char *message) {
|
||||
fprintf(stderr, "%s\n", message);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void oom(void) {
|
||||
die("Query: out of memory");
|
||||
}
|
||||
|
||||
static void except(void) {
|
||||
if ((*jenv)->ExceptionCheck(jenv))
|
||||
die("Query: unexpected Java exception");
|
||||
}
|
||||
|
||||
static void do_at_exit(void) {
|
||||
(*jvm)->DestroyJavaVM(jvm);
|
||||
}
|
||||
|
||||
static void require_jvm(void) {
|
||||
JavaVMInitArgs args;
|
||||
|
||||
if (jvm)
|
||||
return;
|
||||
|
||||
args.version = JNI_VERSION_1_4;
|
||||
args.nOptions = 0;
|
||||
args.options = NULL;
|
||||
args.ignoreUnrecognized = JNI_FALSE;
|
||||
if (JNI_CreateJavaVM(&jvm, (void **)&jenv, &args) != JNI_OK)
|
||||
die("Query: can't create Java VM");
|
||||
atexit(do_at_exit);
|
||||
}
|
||||
|
||||
int Query(char *data, size_t *length) {
|
||||
jclass cQuery;
|
||||
jmethodID mcall;
|
||||
jintArray jlength;
|
||||
jint jlength0;
|
||||
jbyteArray jdata;
|
||||
jboolean result;
|
||||
|
||||
jlength0 = (jint)length[0];
|
||||
if ((size_t)jlength0 != length[0])
|
||||
die("Query: length is too large for Java array");
|
||||
|
||||
require_jvm();
|
||||
|
||||
/* Create a local frame for references to Java objects. */
|
||||
if ((*jenv)->PushLocalFrame(jenv, 16))
|
||||
oom();
|
||||
|
||||
/* Look for class Query, static boolean call(byte[], int[]) */
|
||||
cQuery = (*jenv)->FindClass(jenv, "Query");
|
||||
if (cQuery == NULL)
|
||||
die("Query: can't find Query.class");
|
||||
mcall = (*jenv)->GetStaticMethodID(jenv, cQuery, "call", "([B[I)Z");
|
||||
if (mcall == NULL)
|
||||
die("Query: missing call() method");
|
||||
|
||||
/*
|
||||
* Make arguments to Query.call(). We can't pass data[] and
|
||||
* length[] to Java, so we make new Java arrays jdata[] and
|
||||
* jlength[].
|
||||
*/
|
||||
jdata = (*jenv)->NewByteArray(jenv, (jsize)jlength0);
|
||||
if (jdata == NULL)
|
||||
oom();
|
||||
jlength = (*jenv)->NewIntArray(jenv, 1);
|
||||
if (jlength == NULL)
|
||||
oom();
|
||||
|
||||
/* Set jlength[0] = length[0]. */
|
||||
(*jenv)->SetIntArrayRegion(jenv, jlength, 0, 1, &jlength0);
|
||||
except();
|
||||
|
||||
/*
|
||||
* Call our Java method.
|
||||
*/
|
||||
result = (*jenv)->CallStaticBooleanMethod
|
||||
(jenv, cQuery, mcall, jdata, jlength);
|
||||
except();
|
||||
|
||||
/*
|
||||
* Set length[0] = jlength[0].
|
||||
* Copy length[0] bytes from jdata[] to data[].
|
||||
*/
|
||||
(*jenv)->GetIntArrayRegion(jenv, jlength, 0, 1, &jlength0);
|
||||
except();
|
||||
length[0] = (size_t)jlength0;
|
||||
(*jenv)->GetByteArrayRegion
|
||||
(jenv, jdata, 0, (jsize)jlength0, (jbyte *)data);
|
||||
|
||||
/* Drop our local frame and its references. */
|
||||
(*jenv)->PopLocalFrame(jenv, NULL);
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# Makefile
|
||||
|
||||
# Edit these lines to match your JDK.
|
||||
JAVA_HOME = /Library/Java/Home
|
||||
CPPFLAGS = -I$(JAVA_HOME)/include
|
||||
LIBS = -framework JavaVM
|
||||
JAVAC = $(JAVA_HOME)/bin/javac
|
||||
CC = cc
|
||||
|
||||
all: calljava Query.class
|
||||
|
||||
calljava: main.o query-jni.o
|
||||
$(CC) -o calljava main.o query-jni.o $(LIBS)
|
||||
|
||||
.SUFFIXES: .c .class .java .o
|
||||
.c.o:
|
||||
$(CC) $(CPPFLAGS) -c $<
|
||||
.java.class:
|
||||
$(JAVAC) $<
|
||||
|
||||
clean:
|
||||
rm -f calljava main.o query-jni.o Query.class
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// Kotlin Native v0.6
|
||||
|
||||
import kotlinx.cinterop.*
|
||||
import platform.posix.*
|
||||
|
||||
fun query(data: CPointer<ByteVar>, length: CPointer<size_tVar>): Int {
|
||||
val s = "Here am I"
|
||||
val strLen = s.length
|
||||
val bufferSize = length.pointed.value
|
||||
if (strLen > bufferSize) return 0 // buffer not large enough
|
||||
for (i in 0 until strLen) data[i] = s[i].toByte()
|
||||
length.pointed.value = strLen.signExtend<size_t>()
|
||||
return 1
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef KONAN_LIBQUERY_H
|
||||
#define KONAN_LIBQUERY_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
typedef unsigned char libQuery_KBoolean;
|
||||
typedef char libQuery_KByte;
|
||||
typedef unsigned short libQuery_KChar;
|
||||
typedef short libQuery_KShort;
|
||||
typedef int libQuery_KInt;
|
||||
typedef long long libQuery_KLong;
|
||||
typedef float libQuery_KFloat;
|
||||
typedef double libQuery_KDouble;
|
||||
typedef void* libQuery_KNativePtr;
|
||||
struct libQuery_KType;
|
||||
typedef struct libQuery_KType libQuery_KType;
|
||||
|
||||
typedef struct {
|
||||
/* Service functions. */
|
||||
void (*DisposeStablePointer)(libQuery_KNativePtr ptr);
|
||||
void (*DisposeString)(const char* string);
|
||||
libQuery_KBoolean (*IsInstance)(libQuery_KNativePtr ref, const libQuery_KType* type);
|
||||
|
||||
/* User functions. */
|
||||
struct {
|
||||
struct {
|
||||
libQuery_KInt (*query)(void* data, void* length);
|
||||
} root;
|
||||
} kotlin;
|
||||
} libQuery_ExportedSymbols;
|
||||
extern libQuery_ExportedSymbols* libQuery_symbols(void);
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
#endif /* KONAN_LIBQUERY_H */
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "libQuery_api.h"
|
||||
|
||||
static int Query (char * Data, size_t * Length)
|
||||
{
|
||||
return libQuery_symbols() -> kotlin.root.query(Data, Length);
|
||||
}
|
||||
|
||||
int main (int argc, char * argv [])
|
||||
{
|
||||
char Buffer [1024];
|
||||
size_t Size = sizeof (Buffer);
|
||||
|
||||
if (0 == Query (Buffer, &Size))
|
||||
{
|
||||
printf ("failed to call Query\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char * Ptr = Buffer;
|
||||
while (Size-- > 0) putchar (*Ptr++);
|
||||
putchar ('\n');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
Section Header
|
||||
|
||||
+ name := QUERY;
|
||||
- external := `#define main _query_main`;
|
||||
- external := `#define query Query`;
|
||||
|
||||
Section External
|
||||
|
||||
- query(buffer : NATIVE_ARRAY[CHARACTER], size : NATIVE_ARRAY[INTEGER]) : INTEGER <- (
|
||||
+ s : STRING_CONSTANT;
|
||||
+ len, result : INTEGER;
|
||||
s := "Here am I";
|
||||
len := s.count;
|
||||
(len > size.item(0)).if {
|
||||
result := 0;
|
||||
} else {
|
||||
1.to len do { i : INTEGER;
|
||||
buffer.put (s @ i) to (i - 1);
|
||||
};
|
||||
size.put len to 0;
|
||||
result := 1;
|
||||
};
|
||||
result
|
||||
);
|
||||
|
||||
Section Public
|
||||
|
||||
- main <- (
|
||||
+ buffer : NATIVE_ARRAY[CHARACTER];
|
||||
+ size : NATIVE_ARRAY[INTEGER];
|
||||
query(buffer, size); // need this to pull the query() method
|
||||
);
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
TARGET=test_query
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): main.o query.o
|
||||
gcc -o $@ main.o query.o
|
||||
|
||||
.c.o:
|
||||
gcc -c $<
|
||||
|
||||
query.c: query.li
|
||||
-lisaac $<
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET) *.o query.c
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
:- module query.
|
||||
:- interface.
|
||||
|
||||
:- pred query(string::in, string::out) is det.
|
||||
|
||||
:- implementation.
|
||||
|
||||
query(_, "Hello, world!").
|
||||
|
||||
:- pragma foreign_export("C", query(in, out), "query").
|
||||
|
||||
:- pragma foreign_decl("C",
|
||||
"
|
||||
#include <string.h>
|
||||
int Query (char * Data, size_t * Length);
|
||||
").
|
||||
:- pragma foreign_code("C",
|
||||
"
|
||||
int Query (char *Data, size_t *Length) {
|
||||
MR_String input, result;
|
||||
MR_allocate_aligned_string_msg(input, *Length, MR_ALLOC_ID);
|
||||
memmove(input, Data, *Length);
|
||||
query(input, &result);
|
||||
*Length = strlen(result);
|
||||
memmove(Data, result, *Length);
|
||||
return 1;
|
||||
}
|
||||
").
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
proc Query*(data: var array[1024, char], length: var cint): cint {.exportc.} =
|
||||
const text = "Here am I"
|
||||
if length < text.len:
|
||||
return 0
|
||||
|
||||
for i in 0 .. text.high:
|
||||
data[i] = text[i]
|
||||
length = text.len
|
||||
return 1
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include <stdio.h>
|
||||
|
||||
extern int Query (char * Data, size_t * Length);
|
||||
|
||||
int main (int argc, char * argv [])
|
||||
{
|
||||
char Buffer [1024];
|
||||
size_t Size = sizeof (Buffer);
|
||||
|
||||
if (0 == Query (Buffer, &Size))
|
||||
{
|
||||
printf ("failed to call Query\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char * Ptr = Buffer;
|
||||
while (Size-- > 0) putchar (*Ptr++);
|
||||
putchar ('\n');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <caml/mlvalues.h>
|
||||
#include <caml/callback.h>
|
||||
|
||||
extern int Query (char * Data, size_t * Length)
|
||||
{
|
||||
static value * closure_f = NULL;
|
||||
if (closure_f == NULL) {
|
||||
closure_f = caml_named_value("Query function cb");
|
||||
}
|
||||
value ret = caml_callback(*closure_f, Val_unit);
|
||||
*Length = Int_val(Field(ret, 1));
|
||||
strncpy(Data, String_val(Field(ret, 0)), *Length);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main (int argc, char * argv [])
|
||||
{
|
||||
char Buffer [1024];
|
||||
unsigned Size = 0;
|
||||
|
||||
caml_main(argv); /* added from the original main */
|
||||
|
||||
if (0 == Query (Buffer, &Size))
|
||||
{
|
||||
printf ("failed to call Query\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
char * Ptr = Buffer;
|
||||
printf("size: %d\n", Size);
|
||||
while (Size-- > 0) putchar (*Ptr++);
|
||||
putchar ('\n');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
let caml_query () =
|
||||
let s = "Here am I" in
|
||||
(s, String.length s)
|
||||
;;
|
||||
|
||||
let () =
|
||||
Callback.register "Query function cb" caml_query;
|
||||
;;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include <extensions/embed.h>
|
||||
|
||||
#define min(x,y) (x < y ? x : y)
|
||||
|
||||
extern unsigned char repl[];
|
||||
int Query(char *Data, size_t *Length) {
|
||||
ol_t ol;
|
||||
embed_new(&ol, repl, 0);
|
||||
|
||||
word s = embed_eval(&ol, new_string(&ol,
|
||||
"(define sample \"Here am I\")"
|
||||
"sample"
|
||||
), 0);
|
||||
if (!is_string(s))
|
||||
goto fail;
|
||||
|
||||
int i = *Length = min(string_length(s), *Length);
|
||||
|
||||
memcpy(Data, string_value(s), i);
|
||||
*Length = i;
|
||||
|
||||
OL_free(ol.vm);
|
||||
return 1;
|
||||
fail:
|
||||
OL_free(ol.vm);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <extensions/embed.h>
|
||||
|
||||
extern unsigned char repl[];
|
||||
int Query(char *Data, size_t *Length) {
|
||||
ol_t ol;
|
||||
embed_new(&ol, repl, 0);
|
||||
|
||||
embed_eval(&ol, new_string(&ol,
|
||||
"(import (otus ffi))"
|
||||
"(define lib (load-dynamic-library #f))"
|
||||
"(define memcpy (lib fft-void* \"memcpy\" fft-void* type-string fft-int))"
|
||||
"(define (Query Data Length)"
|
||||
" (define sample (c-string \"Here am I\"))"
|
||||
" (when (memcpy Data sample (min (string-length sample) Length))"
|
||||
" (min (string-length sample) Length)))"
|
||||
), 0);
|
||||
word r =
|
||||
embed_eval(&ol, new_string(&ol, "Query"), new_vptr(&ol, Data), make_integer(*Length), 0);
|
||||
if (!is_number(r))
|
||||
goto fail;
|
||||
*Length = ol2int(r);
|
||||
|
||||
OL_free(ol.vm);
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
OL_free(ol.vm);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
Strchr(Vecsmall(apply(k->if(k>96&&k<123,(k-84)%26+97,if(k>64&&k<91,(k-52)%26+65,k)),Vec(Vecsmall(s)))))
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#include <pari/pari.h>
|
||||
|
||||
#define PARI_SECRET "s=\"Urer V nz\";Strchr(Vecsmall(apply(k->if(k>96&&k<123,(k-84)%26+97,if(k>64&&k<91,(k-52)%26+65,k)),Vec(Vecsmall(s)))))"
|
||||
|
||||
int Query(char *Data, size_t *Length)
|
||||
{
|
||||
int rc = 0;
|
||||
GEN result;
|
||||
|
||||
pari_init(1000000, 2);
|
||||
|
||||
result = geval(strtoGENstr(PARI_SECRET)); /* solve the secret */
|
||||
|
||||
if (result) {
|
||||
strncpy(Data, GSTR(result), *Length); /* return secret */
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
pari_close();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
(notonline)-->
|
||||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (peek/poke, call_back)</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">Here_am_I</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"Here am I"</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">Query</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">pData</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pLength</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peekNS</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pLength</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">machine_word</span><span style="color: #0000FF;">(),</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">poke_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pData</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Here_am_I</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #7060A8;">pokeN</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pLength</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Here_am_I</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">machine_word</span><span style="color: #0000FF;">())</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">Query_cb</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">call_back</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Query</span><span style="color: #0000FF;">)</span>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
(let (Str "Here am I" Len (format (opt))) # Get length from command line
|
||||
(unless (>= (size Str) Len) # Check buffer size
|
||||
(prinl Str) ) ) # Return string if OK
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
int Query(char *Data, size_t *Length) {
|
||||
FILE *fp;
|
||||
char buf[64];
|
||||
|
||||
sprintf(buf, "/usr/bin/picolisp query.l %d -bye", *Length);
|
||||
if (!(fp = popen(buf, "r")))
|
||||
return 0;
|
||||
fgets(Data, *Length, fp);
|
||||
*Length = strlen(Data);
|
||||
return pclose(fp) >= 0 && *Length != 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# store this in file rc_embed.py
|
||||
# store this in file rc_embed.py
|
||||
def query(buffer_length):
|
||||
message = b'Here am I'
|
||||
L = len(message)
|
||||
return message[0:L*(L <= buffer_length)]
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#if 0
|
||||
//I rewrote the driver according to good sense, my style,
|
||||
//and discussion --Kernigh 15:45, 12 February 2011 (UTC).
|
||||
#endif
|
||||
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
|
||||
extern int Query(char*,unsigned*);
|
||||
|
||||
int main(int argc,char*argv[]) {
|
||||
char Buffer[1024], *pc;
|
||||
unsigned Size = sizeof(Buffer);
|
||||
if (!Query(Buffer,&Size))
|
||||
fputs("Failed to call Query",stdout);
|
||||
else
|
||||
for (pc = Buffer; Size--; ++pc)
|
||||
putchar(*pc);
|
||||
putchar('\n');
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<string.h>
|
||||
#include<Python.h>
|
||||
|
||||
int Query(char*Data,unsigned*Length) {
|
||||
char *module = "rc_embed", *function = "query";
|
||||
PyObject *pName, *pModule, *pFunc, *pResult, *pArgs, *pLength;
|
||||
long result = 0;
|
||||
if (!Py_IsInitialized())
|
||||
Py_Initialize();
|
||||
pName = PyUnicode_FromString(module);
|
||||
pModule = PyImport_Import(pName);
|
||||
Py_DECREF(pName);
|
||||
if (NULL == pModule) {
|
||||
PyErr_Print();
|
||||
fprintf(stderr,"Failed to load \"%s\"\n",module);
|
||||
return 0;
|
||||
}
|
||||
pFunc = PyObject_GetAttrString(pModule,function);
|
||||
if ((NULL == pFunc) || (!PyCallable_Check(pFunc))) {
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
fprintf(stderr,"Cannot find function \"%s\"\n",function);
|
||||
if (NULL != pFunc)
|
||||
Py_DECREF(pFunc);
|
||||
Py_DECREF(pModule);
|
||||
return 0;
|
||||
}
|
||||
pArgs = PyTuple_New(1);
|
||||
pLength = PyLong_FromUnsignedLong((unsigned long)(*Length));
|
||||
if (NULL == pLength) {
|
||||
Py_DECREF(pArgs);
|
||||
Py_DECREF(pFunc);
|
||||
Py_DECREF(pModule);
|
||||
return 0;
|
||||
}
|
||||
PyTuple_SetItem(pArgs,0,pLength);
|
||||
pResult = PyObject_CallObject(pFunc, pArgs);
|
||||
if (NULL == pResult)
|
||||
result = 0;
|
||||
else if (!PyBytes_Check(pResult)) {
|
||||
result = 0;
|
||||
Py_DECREF(pResult);
|
||||
} else {
|
||||
if (! PyBytes_Size(pResult))
|
||||
result = 0;
|
||||
else {
|
||||
*Length = (unsigned)PyBytes_Size(pResult);
|
||||
strncpy(Data,PyBytes_AsString(pResult),*Length);
|
||||
Py_DECREF(pResult);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
Py_DECREF(pArgs);
|
||||
Py_DECREF(pFunc);
|
||||
Py_DECREF(pModule);
|
||||
Py_Finalize();
|
||||
return result;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
$ make main.o
|
||||
cc -c -o main.o main.c
|
||||
$ D=$( dirname $( which python3 ) )
|
||||
$ gcc $( $D/python3.2-config --cflags ) -c Query.c
|
||||
In file included from /usr/include/python3.2mu/Python.h:8:0,
|
||||
from Q.c:18:
|
||||
/usr/include/python3.2mu/pyconfig.h:1173:0: warning: "_POSIX_C_SOURCE" redefined [enabled by default]
|
||||
/usr/include/features.h:214:0: note: this is the location of the previous definition
|
||||
$ gcc -o main main.o Query.o $( $D/python3.2-config --ldflags )
|
||||
$ ./main
|
||||
Here am I
|
||||
$
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
typedef int strfun (char * Data, size_t * Length);
|
||||
strfun *Query = NULL;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#lang racket
|
||||
|
||||
(require ffi/unsafe)
|
||||
|
||||
(define xlib (ffi-lib "./x.so"))
|
||||
|
||||
(set-ffi-obj! "Query" xlib (_fun _pointer _pointer -> _bool)
|
||||
(λ(bs len)
|
||||
(define out #"Here I am")
|
||||
(let ([bs (make-sized-byte-string bs (ptr-ref len _int))])
|
||||
(and ((bytes-length out) . <= . (bytes-length bs))
|
||||
(begin (bytes-copy! bs 0 out)
|
||||
(ptr-set! len _int (bytes-length out))
|
||||
#t)))))
|
||||
|
||||
((get-ffi-obj "main" xlib (_fun _int (_list i _bytes) -> _void))
|
||||
0 '())
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env raku
|
||||
|
||||
sub MAIN (Int :l(:len(:$length))) {
|
||||
my Str $String = "Here am I";
|
||||
$*OUT.print: $String if $String.codes ≤ $length
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#include<stdio.h>
|
||||
#include<stddef.h>
|
||||
#include<string.h>
|
||||
|
||||
int Query(char *Data, size_t *Length) {
|
||||
FILE *fp;
|
||||
char buf[64];
|
||||
|
||||
sprintf(buf, "/home/user/query.raku --len=%zu", *Length);
|
||||
if (!(fp = popen(buf, "r")))
|
||||
return 0;
|
||||
fgets(Data, *Length, fp);
|
||||
*Length = strlen(Data);
|
||||
return pclose(fp) >= 0 && *Length != 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# query.rb
|
||||
require 'fiddle'
|
||||
|
||||
# Look for a C variable named QueryPointer.
|
||||
# Raise an error if it is missing.
|
||||
c_var = Fiddle.dlopen(nil)['QueryPointer']
|
||||
|
||||
int = Fiddle::TYPE_INT
|
||||
voidp = Fiddle::TYPE_VOIDP
|
||||
sz_voidp = Fiddle::SIZEOF_VOIDP
|
||||
|
||||
# Implement the C function
|
||||
# int Query(void *data, size_t *length)
|
||||
# in Ruby code. Store it in a global constant in Ruby (named Query)
|
||||
# to protect it from Ruby's garbage collector.
|
||||
#
|
||||
Query = Fiddle::Closure::BlockCaller
|
||||
.new(int, [voidp, voidp]) do |datap, lengthp|
|
||||
message = "Here am I"
|
||||
|
||||
# We got datap and lengthp as Fiddle::Pointer objects.
|
||||
# Read length, assuming sizeof(size_t) == sizeof(void *).
|
||||
length = lengthp[0, sz_voidp].unpack('J').first
|
||||
|
||||
# Does the message fit in length bytes?
|
||||
if length < message.bytesize
|
||||
0 # failure
|
||||
else
|
||||
length = message.bytesize
|
||||
datap[0, length] = message # Copy the message.
|
||||
lengthp[0, sz_voidp] = [length].pack('J') # Update the length.
|
||||
1 # success
|
||||
end
|
||||
end
|
||||
|
||||
# Set the C variable to our Query.
|
||||
Fiddle::Pointer.new(c_var)[0, sz_voidp] = [Query.to_i].pack('J')
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/* query-rb.c */
|
||||
#include <stdlib.h>
|
||||
#include <ruby.h>
|
||||
|
||||
/*
|
||||
* QueryPointer() uses Ruby and may raise a Ruby error. Query() is a
|
||||
* C wrapper around QueryPointer() that loads Ruby, sets QueryPointer,
|
||||
* and protects against Ruby errors.
|
||||
*/
|
||||
int (*QueryPointer)(char *, size_t *) = NULL;
|
||||
|
||||
static int in_bad_exit = 0;
|
||||
|
||||
static void
|
||||
do_at_exit(void)
|
||||
{
|
||||
RUBY_INIT_STACK;
|
||||
|
||||
if (!in_bad_exit)
|
||||
ruby_cleanup(0);
|
||||
}
|
||||
|
||||
static void
|
||||
bad_exit(int state)
|
||||
{
|
||||
in_bad_exit = 1;
|
||||
ruby_stop(state); /* Clean up Ruby and exit the process. */
|
||||
}
|
||||
|
||||
static void
|
||||
require_query(void)
|
||||
{
|
||||
static int done = 0;
|
||||
int state;
|
||||
|
||||
if (done)
|
||||
return;
|
||||
done = 1;
|
||||
|
||||
ruby_init();
|
||||
atexit(do_at_exit);
|
||||
ruby_init_loadpath(); /* needed to require 'fiddle' */
|
||||
|
||||
/* Require query.rb in current directory. */
|
||||
rb_eval_string_protect("require_relative 'query'", &state);
|
||||
if (!state && !QueryPointer)
|
||||
rb_eval_string_protect("fail 'missing QueryPointer'", &state);
|
||||
if (state)
|
||||
bad_exit(state); /* Ruby will report the error. */
|
||||
}
|
||||
|
||||
struct args {
|
||||
char *data;
|
||||
size_t *length;
|
||||
int result;
|
||||
};
|
||||
|
||||
static VALUE
|
||||
Query1(VALUE v) {
|
||||
struct args *a = (struct args *)v;
|
||||
a->result = QueryPointer(a->data, a->length);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
int
|
||||
Query(char *data, size_t *length)
|
||||
{
|
||||
struct args a;
|
||||
int state;
|
||||
RUBY_INIT_STACK;
|
||||
|
||||
require_query();
|
||||
|
||||
/* Call QueryPointer(), protect against errors. */
|
||||
a.data = data;
|
||||
a.length = length;
|
||||
rb_protect(Query1, (VALUE)&a, &state);
|
||||
if (state)
|
||||
bad_exit(state);
|
||||
return a.result;
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# Rakefile
|
||||
|
||||
# To build and run:
|
||||
# $ rake
|
||||
# $ ./callruby
|
||||
|
||||
# Must link with cc -Wl,-E so query.c exports QueryPointer.
|
||||
CC = ENV.fetch('CC', 'cc')
|
||||
LDFLAGS = '-Wl,-E'
|
||||
CPPFLAGS = RbConfig.expand('-I$(rubyarchhdrdir) -I$(rubyhdrdir)')
|
||||
LIBS = RbConfig.expand('$(LIBRUBYARG) $(LIBS)')
|
||||
|
||||
task 'default' => 'callruby'
|
||||
|
||||
desc 'compiles callruby'
|
||||
file 'callruby' => %w[main.o query-rb.o] do |t|
|
||||
sh "#{CC} #{LDFLAGS} -o #{t.name} #{t.sources.join(' ')} #{LIBS}"
|
||||
end
|
||||
|
||||
rule '.o' => %w[.c] do |t|
|
||||
sh "#{CC} #{CPPFLAGS} -o #{t.name} -c #{t.source}"
|
||||
end
|
||||
|
||||
desc 'removes callruby and .o files'
|
||||
task 'clean' do
|
||||
rm_f %w[callruby main.o query-rb.o]
|
||||
end
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//! In order to run this task, you will need to compile the C program locating in the task linked
|
||||
//! above. The C program will need to be linked with the library produced by this file.
|
||||
//!
|
||||
//! 1. Compile this library:
|
||||
//!
|
||||
//! ```bash
|
||||
//! $ cargo build --release
|
||||
//! ```
|
||||
//!
|
||||
//! 2. Copy the C program into query.c.
|
||||
//! 3. Compile and link the C program with the produced library:
|
||||
//!
|
||||
//! ```bash
|
||||
//! $ LD_LIBRARY_PATH=/path/to/library gcc query.c -o query -Wall -Werror libquery
|
||||
//! ```
|
||||
//! 4. Run the resulting binary.
|
||||
//!
|
||||
//! ```bash
|
||||
//! $ LD_LIBRARY_PATH=/path/to/library ./query
|
||||
//! Here am I
|
||||
//! ```
|
||||
|
||||
#![crate_type = "cdylib"]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use std::ffi::CString;
|
||||
|
||||
use libc::{c_char, c_int, size_t};
|
||||
|
||||
#[no_mangle]
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(clippy::missing_safety_doc)]
|
||||
pub unsafe extern "C" fn Query(data: *mut c_char, length: *mut size_t) -> c_int {
|
||||
let string = "Here am I";
|
||||
if *length + 1 < string.len() {
|
||||
0
|
||||
} else {
|
||||
let c_string = CString::new(string).unwrap();
|
||||
libc::strcpy(data, c_string.as_ptr());
|
||||
*length = string.len();
|
||||
1
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/* Query.scala */
|
||||
object Query {
|
||||
def call(data: Array[Byte], length: Array[Int]): Boolean = {
|
||||
val message = "Here am I"
|
||||
val mb = message.getBytes("utf-8")
|
||||
if (length(0) >= mb.length) {
|
||||
length(0) = mb.length
|
||||
System.arraycopy(mb, 0, data, 0, mb.length)
|
||||
true
|
||||
} else false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/* query-jni.c */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <jni.h>
|
||||
|
||||
static JavaVM *jvm = NULL;
|
||||
static JNIEnv *jenv = NULL;
|
||||
|
||||
static void die(const char *message) {
|
||||
fprintf(stderr, "%s\n", message);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void oom(void) {
|
||||
die("Query: out of memory");
|
||||
}
|
||||
|
||||
static void except(void) {
|
||||
if ((*jenv)->ExceptionCheck(jenv))
|
||||
die("Query: unexpected Java exception");
|
||||
}
|
||||
|
||||
static void do_at_exit(void) {
|
||||
(*jvm)->DestroyJavaVM(jvm);
|
||||
}
|
||||
|
||||
static void require_jvm(void) {
|
||||
JavaVMInitArgs args;
|
||||
|
||||
if (jvm)
|
||||
return;
|
||||
|
||||
args.version = JNI_VERSION_1_4;
|
||||
args.nOptions = 0;
|
||||
args.options = NULL;
|
||||
args.ignoreUnrecognized = JNI_FALSE;
|
||||
if (JNI_CreateJavaVM(&jvm, (void **)&jenv, &args) != JNI_OK)
|
||||
die("Query: can't create Java VM");
|
||||
atexit(do_at_exit);
|
||||
}
|
||||
|
||||
int Query(char *data, size_t *length) {
|
||||
jclass cQuery;
|
||||
jmethodID mcall;
|
||||
jintArray jlength;
|
||||
jint jlength0;
|
||||
jbyteArray jdata;
|
||||
jboolean result;
|
||||
|
||||
jlength0 = (jint)length[0];
|
||||
if ((size_t)jlength0 != length[0])
|
||||
die("Query: length is too large for Scala array");
|
||||
|
||||
require_jvm();
|
||||
|
||||
/* Create a local frame for references to Scala objects. */
|
||||
if ((*jenv)->PushLocalFrame(jenv, 16))
|
||||
oom();
|
||||
|
||||
/* Look for class Query, static boolean call(byte[], int[]) */
|
||||
cQuery = (*jenv)->FindClass(jenv, "Query");
|
||||
if (cQuery == NULL)
|
||||
die("Query: can't find Query.class");
|
||||
mcall = (*jenv)->GetStaticMethodID(jenv, cQuery, "call", "([B[I)Z");
|
||||
if (mcall == NULL)
|
||||
die("Query: missing call() method");
|
||||
|
||||
/*
|
||||
* Make arguments to Query.call(). We can't pass data[] and
|
||||
* length[] to Scala, so we make new Scala arrays jdata[] and
|
||||
* jlength[].
|
||||
*/
|
||||
jdata = (*jenv)->NewByteArray(jenv, (jsize)jlength0);
|
||||
if (jdata == NULL)
|
||||
oom();
|
||||
jlength = (*jenv)->NewIntArray(jenv, 1);
|
||||
if (jlength == NULL)
|
||||
oom();
|
||||
|
||||
/* Set jlength[0] = length[0]. */
|
||||
(*jenv)->SetIntArrayRegion(jenv, jlength, 0, 1, &jlength0);
|
||||
except();
|
||||
|
||||
/*
|
||||
* Call our Scala method.
|
||||
*/
|
||||
result = (*jenv)->CallStaticBooleanMethod
|
||||
(jenv, cQuery, mcall, jdata, jlength);
|
||||
except();
|
||||
|
||||
/*
|
||||
* Set length[0] = jlength[0].
|
||||
* Copy length[0] bytes from jdata[] to data[].
|
||||
*/
|
||||
(*jenv)->GetIntArrayRegion(jenv, jlength, 0, 1, &jlength0);
|
||||
except();
|
||||
length[0] = (size_t)jlength0;
|
||||
(*jenv)->GetByteArrayRegion
|
||||
(jenv, jdata, 0, (jsize)jlength0, (jbyte *)data);
|
||||
|
||||
/* Drop our local frame and its references. */
|
||||
(*jenv)->PopLocalFrame(jenv, NULL);
|
||||
|
||||
return (int)result;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# Makefile
|
||||
|
||||
# Edit these lines to match your JDK.
|
||||
JAVA_HOME = /Library/Java/Home
|
||||
CPPFLAGS = -I$(JAVA_HOME)/include
|
||||
LIBS = -framework JavaVM
|
||||
JAVAC = $(JAVA_HOME)/bin/javac
|
||||
CC = cc
|
||||
|
||||
all: calljava Query.class
|
||||
|
||||
calljava: main.o query-jni.o
|
||||
$(CC) -o calljava main.o query-jni.o $(LIBS)
|
||||
|
||||
.SUFFIXES: .c .class .java .o
|
||||
.c.o:
|
||||
$(CC) $(CPPFLAGS) -c $<
|
||||
.java.class:
|
||||
$(JAVAC) $<
|
||||
|
||||
clean:
|
||||
rm -f calljava main.o query-jni.o Query.class
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int query(int (*callback)(char *, size_t *))
|
||||
{
|
||||
char buffer[1024];
|
||||
size_t size = sizeof buffer;
|
||||
|
||||
if (callback(buffer, &size) == 0) {
|
||||
puts("query: callback failed");
|
||||
} else {
|
||||
char *ptr = buffer;
|
||||
|
||||
while (size-- > 0)
|
||||
putchar (*ptr++);
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
gcc -g -fPIC query.c -c
|
||||
gcc -g --shared query.c -o query.c
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
(with-dyn-lib "./query.so"
|
||||
(deffi query "query" void (closure)))
|
||||
|
||||
(deffi-cb query-cb int ((carray char) (ptr (array 1 size-t))))
|
||||
|
||||
(query (query-cb (lambda (buf sizeptr)
|
||||
(symacrolet ((size [sizeptr 0]))
|
||||
(let* ((s "Here am I")
|
||||
(l (length s)))
|
||||
(cond
|
||||
((> l size) 0)
|
||||
(t (carray-set-length buf size)
|
||||
(carray-put buf s)
|
||||
(set size l))))))))
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
(with-dyn-lib "./query.so"
|
||||
(deffi query "query" void (closure)))
|
||||
|
||||
(with-dyn-lib nil
|
||||
(deffi memcpy "memcpy" cptr (cptr str size-t)))
|
||||
|
||||
(deffi-cb query-cb int (cptr (ptr (array 1 size-t))))
|
||||
|
||||
(query (query-cb (lambda (buf sizeptr) ; int lambda(void *buf, siz
|
||||
(symacrolet ((size [sizeptr 0])) ; { #define size sizeptr[0]
|
||||
(let* ((s "Here am I") ; char *s = "Here am I";
|
||||
(l (length s))) ; size_t l = strlen(s);
|
||||
(cond ; if (length > size)
|
||||
((> l size) 0) ; { return 0; } else
|
||||
(t (memcpy buf s l) ; { memcpy(buf, s, l);
|
||||
(set size l)))))))) ; return size = l; } }
|
||||
|
|
@ -0,0 +1 @@
|
|||
(deffi-cb query-cb int (cptr (ptr (array 1 size-t))) -1)
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
int Query (char * Data, size_t * Length) {
|
||||
Tcl_Obj *arguments[2];
|
||||
int code;
|
||||
|
||||
arguments[0] = Tcl_NewStringObj("Query", -1); /* -1 for "use up to zero byte" */
|
||||
arguments[1] = Tcl_NewStringObj(Data, Length);
|
||||
Tcl_IncrRefCount(arguments[0]);
|
||||
Tcl_IncrRefCount(arguments[1]);
|
||||
if (Tcl_EvalObjv(interp, 2, arguments, 0) != TCL_OK) {
|
||||
/* Was an error or other exception; report here... */
|
||||
Tcl_DecrRefCount(arguments[0]);
|
||||
Tcl_DecrRefCount(arguments[1]);
|
||||
return 0;
|
||||
}
|
||||
Tcl_DecrRefCount(arguments[0]);
|
||||
Tcl_DecrRefCount(arguments[1]);
|
||||
if (Tcl_GetObjResult(NULL, Tcl_GetObjResult(interp), &code) != TCL_OK) {
|
||||
/* Not an integer result */
|
||||
return 0;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
proc Query data {
|
||||
puts "Query was $data"
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
int Query (char * Data, size_t * Length) {
|
||||
const char *str;
|
||||
int len;
|
||||
|
||||
if (Tcl_Eval(interp, "Query") != TCL_OK) {
|
||||
return 0;
|
||||
}
|
||||
str = Tcl_GetStringFromObj(Tcl_GetObjResult(interp), &len);
|
||||
if (len+1 > Length) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(Data, str, len+1);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
proc Query {} {
|
||||
return "Here am I"
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#include <tcl.h>
|
||||
Tcl_Interp *interp;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Tcl_FindExecutable(argv[0]); /* Initializes library */
|
||||
interp = Tcl_CreateInterp(); /* Make an interpreter */
|
||||
|
||||
/* Rest of contents of main() from task header... */
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/* query.wren */
|
||||
|
||||
class RCQuery {
|
||||
// Both arguments are lists as we need pass by reference here
|
||||
static query(Data, Length) {
|
||||
var s = "Here am I"
|
||||
var sc = s.count
|
||||
if (sc > Length[0]) return 0 // buffer too small
|
||||
for (i in 0...sc) Data[i] = s[i].bytes[0]
|
||||
Length[0] = sc
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
#include <stdio.h>
|
||||
#include "wren.h"
|
||||
|
||||
char *script;
|
||||
WrenVM * vm;
|
||||
|
||||
WrenForeignMethodFn bindForeignMethod(
|
||||
WrenVM* vm,
|
||||
const char* module,
|
||||
const char* className,
|
||||
bool isStatic,
|
||||
const char* signature) {
|
||||
return NULL; // nothing needed here
|
||||
}
|
||||
|
||||
static void writeFn(WrenVM* vm, const char* text) {
|
||||
printf("%s", text);
|
||||
}
|
||||
|
||||
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
|
||||
switch (errorType) {
|
||||
case WREN_ERROR_COMPILE:
|
||||
printf("[%s line %d] [Error] %s\n", module, line, msg);
|
||||
break;
|
||||
case WREN_ERROR_STACK_TRACE:
|
||||
printf("[%s line %d] in %s\n", module, line, msg);
|
||||
break;
|
||||
case WREN_ERROR_RUNTIME:
|
||||
printf("[Runtime Error] %s\n", msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *readFile(const char *fileName) {
|
||||
FILE *f = fopen(fileName, "r");
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
rewind(f);
|
||||
char *script = malloc(fsize + 1);
|
||||
fread(script, 1, fsize, f);
|
||||
fclose(f);
|
||||
script[fsize] = 0;
|
||||
return script;
|
||||
}
|
||||
|
||||
int configWrenVM() {
|
||||
WrenConfiguration config;
|
||||
wrenInitConfiguration(&config);
|
||||
config.writeFn = &writeFn;
|
||||
config.errorFn = &errorFn;
|
||||
config.bindForeignMethodFn = &bindForeignMethod;
|
||||
vm = wrenNewVM(&config);
|
||||
const char* module = "main";
|
||||
const char* fileName = "query.wren";
|
||||
script = readFile(fileName);
|
||||
WrenInterpretResult result = wrenInterpret(vm, module, script);
|
||||
switch (result) {
|
||||
case WREN_RESULT_COMPILE_ERROR:
|
||||
printf("Compile Error!\n");
|
||||
return -1;
|
||||
case WREN_RESULT_RUNTIME_ERROR:
|
||||
printf("Runtime Error!\n");
|
||||
return -1;
|
||||
case WREN_RESULT_SUCCESS:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Query(char *Data, size_t *Length) {
|
||||
int i, r;
|
||||
wrenEnsureSlots(vm, 4);
|
||||
|
||||
// create list for Data, fill with zeros and put in slot 1
|
||||
wrenSetSlotNewList(vm, 1);
|
||||
wrenSetSlotDouble(vm, 2, 0.0);
|
||||
for (i = 0; i < *Length; ++i) wrenInsertInList(vm, 1, i, 2);
|
||||
|
||||
// create list for Length and put in slot 2
|
||||
wrenSetSlotNewList(vm, 2);
|
||||
wrenSetSlotDouble(vm, 3, (double)*Length);
|
||||
wrenInsertInList(vm, 2, 0, 3);
|
||||
|
||||
// get handle to Wren's query method
|
||||
WrenHandle* method = wrenMakeCallHandle(vm, "query(_,_)");
|
||||
|
||||
// get its class and put in slot 0
|
||||
wrenGetVariable(vm, "main", "RCQuery", 0);
|
||||
|
||||
// call the Wren method
|
||||
wrenCall(vm, method);
|
||||
|
||||
// get the result and check it's 1
|
||||
r = (int)wrenGetSlotDouble(vm, 0);
|
||||
if (r) {
|
||||
// get the length of the string from slot 2
|
||||
wrenGetListElement(vm, 2, 0, 3);
|
||||
*Length = (int)wrenGetSlotDouble(vm, 3);
|
||||
|
||||
// copy the bytes from the list in slot 1 to the C buffer
|
||||
for (i = 0; i < *Length; ++i) {
|
||||
wrenGetListElement(vm, 1, i, 3);
|
||||
Data[i] = (char)wrenGetSlotDouble(vm, 3);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int e = configWrenVM();
|
||||
if (!e) {
|
||||
char Buffer [1024];
|
||||
size_t Size = sizeof(Buffer);
|
||||
if (0 == Query(Buffer, &Size)) {
|
||||
printf ("failed to call Query\n");
|
||||
e = 1;
|
||||
} else {
|
||||
char * Ptr = Buffer;
|
||||
while (Size-- > 0) putchar (*Ptr++);
|
||||
putchar ('\n');
|
||||
}
|
||||
}
|
||||
wrenFreeVM(vm);
|
||||
free(script);
|
||||
return e;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
option casemap:none
|
||||
|
||||
|
||||
strlen proto :qword
|
||||
strncpy proto :qword, :qword, :dword
|
||||
|
||||
Query proto :qword, :qword
|
||||
|
||||
.data
|
||||
szstr db "Here am I",0
|
||||
|
||||
.code
|
||||
Query proc Data:qword, len:qword
|
||||
local d:qword, l:qword, s:dword
|
||||
|
||||
mov d, Data
|
||||
mov l, len
|
||||
invoke strlen, addr szstr
|
||||
.if rax <= l
|
||||
mov s, eax
|
||||
invoke strncpy, d, addr szstr, s
|
||||
mov eax, s
|
||||
mov rax, l
|
||||
mov dword ptr [rax], ecx
|
||||
mov rax, 1
|
||||
ret
|
||||
.endif
|
||||
mov rax, 0
|
||||
ret
|
||||
Query endp
|
||||
end
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
section .data
|
||||
szmsg db "Here I am",0
|
||||
|
||||
section .text
|
||||
global Query
|
||||
|
||||
strlen:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
mov rsi, rdi
|
||||
mov rcx, -1
|
||||
_1:
|
||||
inc rcx
|
||||
cmp byte [rsi+rcx], 0
|
||||
jne _1
|
||||
mov rax, rcx
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
Query:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
;;mov r9, rcx ;;Arg 1, windows
|
||||
;;mov r8, rdx ;;Arg 2, windows
|
||||
mov r9, rdi ;;Arg 1, Linux
|
||||
mov r8, rsi ;;Arg 2, Linux
|
||||
lea rdi, szmsg
|
||||
call strlen
|
||||
cmp rax, r8
|
||||
jg _err
|
||||
mov r10d, eax
|
||||
mov rdi, r9
|
||||
lea rsi, szmsg
|
||||
rep movsb
|
||||
mov rax, r8
|
||||
mov dword [rax], r10d
|
||||
jmp _exit
|
||||
|
||||
_err:
|
||||
mov rax, 0
|
||||
|
||||
_exit:
|
||||
pop rbp
|
||||
ret
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
const std = @import("std");
|
||||
|
||||
export fn Query(Data: [*c]u8, Length: *usize) callconv(.C) c_int {
|
||||
const value = "Here I am";
|
||||
|
||||
if (Length.* >= value.len) {
|
||||
@memcpy(@ptrCast([*]u8, Data), value, value.len);
|
||||
Length.* = value.len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// query.c
|
||||
// export zklRoot=/home/ZKL
|
||||
// clang query.c -I $zklRoot/VM -L $zklRoot/Lib -lzkl -pthread -lncurses -o query
|
||||
// LD_LIBRARY_PATH=$zklRoot/Lib ./query
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zklObject.h"
|
||||
#include "zklImports.h"
|
||||
#include "zklClass.h"
|
||||
#include "zklFcn.h"
|
||||
#include "zklString.h"
|
||||
|
||||
int query(char *buf, size_t *sz)
|
||||
{
|
||||
Instance *r;
|
||||
pVM vm;
|
||||
MLIST(mlist,10);
|
||||
|
||||
// Bad practice: not protecting things from the garbage collector
|
||||
|
||||
// build the call parameters: ("query.zkl",False,False,True)
|
||||
mlistBuild(mlist,stringCreate("query.zkl",I_OWNED,NoVM),
|
||||
BoolFalse,BoolFalse,BoolTrue,ZNIL);
|
||||
// Import is in the Vault, a store of useful stuff
|
||||
// We want to call TheVault.Import.import("query.zkl",False,False,True)
|
||||
// which will load/compile/run query.zkl
|
||||
r = fcnRunith("Import","import",(Instance *)mlist,NoVM);
|
||||
// query.zkl is a class with a var that has the query result
|
||||
r = classFindVar(r,"query",0,NoVM); // -->the var contents
|
||||
strcpy(buf,stringText(r)); // decode the string into a char *
|
||||
*sz = strlen(buf); // screw overflow checking
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
char buf[100];
|
||||
size_t sz = sizeof(buf);
|
||||
|
||||
zklConstruct(argc,argv); // initialize the zkl shared library
|
||||
query(buf,&sz);
|
||||
printf("Query() --> \"%s\"\n",buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
// query.zkl
|
||||
var query="Here am I";
|
||||
Loading…
Add table
Add a link
Reference in a new issue