I have long string in C and I want pass this to lua function. but beacause string is long I don't want pass it, I want pass pointer of string to lua. I do this by use lua_pushlightuserdata but in Lua I can't use this pointer.
C code :
char* st = "abcdefghijklmnopqrstuvwxyz1234567890";
lua_getglobal(myLuaState,"kk");
lua_pushlightuserdata(myLuaState,st);
lua_pcall(myLuaState, 1, 0, 0);
Lua code :
function kk(a)
print(a)
end
result of code is:
userdata: 0x41b4d8
you can use ffi in Luajit
function kk(a)
local ffi = require("ffi")
s = ffi.string(a)
print(s)
end
the result is:
abcdefghijklmnopqrstuvwxyz1234567890
Related
I have the following simple C function:
void pyentry(const char *config)
{
printf("%s\n",config);
fflush(stdout);
}
My ctypes definition is as follows:
libc = ct.CDLL("./amr.so")
entry = wrap_function(libc, 'pyentry', ct.POINTER(Checkpoint), [ct.c_wchar_p])
json = "this is a test"
start = entry(json)
Where wrap_function is simply a wrapper for more easily defining ctypes access to C functions:
def wrap_function(lib, funcname, restype, argtypes):
func = lib.__getattr__(funcname)
func.restype = restype
func.argtypes = argtypes
return func
I have compiled as a shared library and I am trying to call it, but in C it is only printing the first character of the string I send in. I am assuming this is because I have the wrong argument tpyes in my ctypes definition, but I am not having any luck figuring out out the right one.
Can someone tell me why my C function is only seeing the first character in the passed string?
Try:
entry = wrap_function(libc, 'pyentry', None, [ct.POINTER(ct.c_char)])
json = "this is a test".encode('utf-8')
pyentry takes const char* and returns void. So argtypes and restype could be [ct.POINTER(ct.c_char)] and None.
And char* points a sequence of bytes, not Python string. So json should be converted to bytes.
I am creating a cross-platform library for Windows and macOS that is written in C, and I need to pass a variable by reference. How do I define the function in C so that it can receive a variable passed by reference, and how do I call the function in Swift?
For example, if I were to define a function in my C library like:
int sayBye(const char* greetingString){
greetingString = "bye";
return 0;
}
and call it in Swift like:
var greeting: String = "hello"
let responseCode = sayBye(greeting)
print(greeting)
I want the print statement to output "bye".
Constraints: "bye" cannot be returned in the return statement.
In short, I want to modify the contents of the string "greeting" after it has been passed by reference to a C-function.
Note: I'm not sure if, in the code above, I am defining the C function correctly or if I am calling it correctly in swift, and I am open to recommendations.
Found something that worked.
In the C library:
int sayBye(const char** greetingString){
*greetingString = "bye";
return 0;
}
Called in Swift:
var greeting = ("hello" as NSString).utf8String
let responseCode = sayBye(&greeting)
let stringFromPointer = String.init(cString: greeting!)
print(stringFromPointer)
I am working on a project that implements a C library using Swift. So far I have been able to manage how to get String from C strings and some others.
Now I am facing an issue when dealing with a C callback that returns OUT variables type char**. The swift code needs to reallocate memory and change the value. These variables are used for String type.
The Header for the C function is:
DllExport void STDCALL DvProviderGetProtocolInfo(THandle aProvider, CallbackGetProtocolInfo aCallback, void* aPtr);
And the header for the C Callback is:
typedef int32_t (STDCALL *CallbackGetProtocolInfo)(void* aPtr, IDvInvocationC* aInvocation, void* aInvocationPtr, char** aSource, char** aSink);
In swift I call the function like that:
DvProviderGetProtocolInfo(prvHandleId, { (pointer, aInvocation, aInvocationPtr, aSource, aSink) -> Int32 in
let senderClass:SenderClass = bridgeToTypeUnretained(ptr: pointer!)
senderClass.writeCStringValue(from: aSource, withValue: senderClass.sourceProtocolInfoArray)
senderClass.writeCStringValue(from: aSink, withValue: senderClass.sinkProtocolInfoArray)
return 0
}, bridgeToPointerRetained(obj: self))
The functions used are:
public func writeCStringValue(from pointer:UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>?, withValue value:String){
pointer!.pointee = UnsafeMutablePointer<Int8>.allocate(capacity:value.utf8.count)
strcpy(pointer!.pointee, value)
}
And declared in another Swift File:
/*** Convert const void* To Any T ***/
func bridgeToTypeRetained<T : AnyObject>(ptr : UnsafeMutableRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
}
func bridgeToTypeUnretained<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}
/*** Convert const void* To Any T ***/
func bridgeToPointerRetained<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passRetained(obj).toOpaque())
}
func bridgeToPointerUnretained<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}
So far, for small values, writeCStringValue function works fine but when I try to send a long String like:
let aTest = "http-get:*:audio/m4a:*,http-get:*:audio/x-m4a:*,http-get:*:audio/aiff:*,http-get:*:audio/x-aiff:*,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3,http-get:*:audio/mp4:*,http-get:*:audio/wav:*,http-get:*:audio/wave:*,http-get:*:audio/x-wav:*,http-get:*:video/mpeg:*,http-get:*:video/mp4:*,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG,http-get:*:image/png:DLNA.ORG_PN=PNG_TN,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG"
I get a EXC_BAD_ACCESS at the end of writeCStringValue function.
If I include the code in writeCStringValue function inside the callback, then there is no crash.
Ideally i would like to use writeCStringValue function.
Am i changing the values of char** correctly?
Thank you
strcpy(pointer!.pointee, value)
creates a temporary C string representation of the Swift string value,
and copies that to the address given by pointer!.pointee.
C strings are delimited by a trailing null character and that is not
taken into account in the allocation
pointer!.pointee = UnsafeMutablePointer<Int8>.allocate(capacity:value.utf8.count)
Therefore strcpy() copies one char more than is allocated. That may or may
not cause a crash, but is undefined behavior in any case.
strdup() does both the allocation and the copy, so a simpler solution is
pointer?.pointee = strdup(value)
That may be better anyway, if the C function (eventually) releases the string with free().
How I can do similar for ruby. I am not able to find a example/documentation for casting a variable to object. For example
Local<Object> obj = args[0]->ToObject();
Local<Array> props = obj->GetPropertyNames();
I am re-writing a node extension in ruby. Any sort of help will be very helpful. Thanks
static Handle<Value> SendEmail(const Arguments& args)
{
HandleScope scope;
list<string> values;
Local<Object> obj = args[0]->ToObject();
Local<Array> props = obj->GetPropertyNames();
// Iterate through args[0], adding each element to our list
for(unsigned int i = 0; i < props->Length(); i++) {
String::AsciiValue val(obj->Get(i)->ToString());
values.push_front(string(*val));
}
// Display the values in the list for debugging purposes
for (list<string>::iterator it = values.begin(); it != values.end(); it++) {
cout << *it << endl;
}
return scope.Close(args.This());
}
I'm not entirely sure that I understand your question, as you flagged this question as C and your code example is C++, but either way, if you're attempting to extend ruby you'll need to convert ruby values to C types, and if you plan on using C++ data structures, from C types to C++ objects.
Using the Ruby C Api:
#include "ruby.h"
//Define module my_module (this can be any name but it should be the name of your extension
VALUE MyModule = Qnil;
//Initialization prototype - required by ruby
void Init_MyModule();
//method prototype declarations - all methods must be prefaced by method_
VALUE method_get_some_ruby_value();
//actual method
VALUE get_some_ruby_value(VALUE self, VALUE some_value)
{
//If your value is a ruby string - the StringValue function from ruby will ensure
//that you get a string no matter what, even if the type being passed is not a string.
VALUE r_string_value = StringValue(some_value);
//Now we tell the Ruby API to give us the pointer to the ruby string
//value and we assign that to a native char * in C.
char *c_string_value = RSTRING_PTR(r_string_value);
//Now do something with the char * - for example, turn it into a C++ string
std::string str(c_string_value);
// ...do something useful here...
return Qnil; // If you want to return something back to ruby, you can return a VALUE.
}
//Ruby calls this to initialize your module in ruby
VALUE Init_MyModule()
{
//This defines your module in ruby
MyModule = rb_define_module("MyModule");
//This defines the method - the module it is in, the ruby method name, the actual method ruby will call, and the number of arguments this function is expected to take
rb_define_method(MyModule, "get_some_ruby_value", get_some_ruby_value, 1);
}
If you want to learn about passing structs back and forth between Ruby/C/C++, you'll need to have a thorough understanding of Ruby and the Ruby C API before you start trying to work with C++ objects.
Here are a few excellent resources to get you started:
http://silverhammermba.github.io/emberb/c/
http://java.ociweb.com/mark/NFJS/RubyCExtensions.pdf
I am using Flex's Alchemy library to generate SWC's out of C files. I have a byte array (unsigned char buffer[size]) in the c-layer that I'd like to return to the ActionScript layer as a ByteArray. Do I have to iterate through the array and explicitly call AS3_Set on each element or is there a way to just return the entire C array at once?
This can be accomplished by using the AS3_ByteArray_writeBytes function of the Alchemy API.
In C, when returning from the function called by Flash, return the pointer to the C-array, like this:
int * myArray = malloc(100);
//populate array...
return AS3_Array("IntType", (int)myArray);
Then, in Flash:
import cmodule.<c module name>.MemUser;
...
memory = new MemUser();
for (var i:int = 0; i<4;i++) { //getting a 4 uints array
trace(memory._mru16(data[0] + i*4)); //data is the return value from C
}
Or use these functions to read the ints/floats/char from the c-array (you can't just use ByteArray.readInt(), the numbers in c are represented differently)