Accessing <objc/runtime.h> from Cycript - ios

I wan't to be able to use associated objects and ISA swizzle, but I can't figure out how to import objc/runtime.h for use with Cycript. I have tried in both the console and in .js files but no luck.
Ideally I'd like to figure out how to include frameworks as well.

It seems like a subset of runtime.h is included by default in the Cycript environment. For example, class_copyMethodList and objc_getClass work without any added effort.
var count = new new Type(#encode(int));
var methods = class_copyMethodList(objc_getClass("NSObject"), count);
However objc_setAssociatedObject is not referenced:
objc_getAssociatedObject(someVar, "asdf")
#ReferenceError: Can't find variable: objc_getAssociatedObject
After a lot of searching, I realized the answer was right under my nose. limneos's weak_classdump uses the runtime to do it's dump and Cycript's tutorial shows how to grab C functions.
The solution I ended up with is this:
function setAssociatedObject(someObject, someValue, constVoidPointer) {
SetAssociatedObject = #encode(void(id, const void*, id, unsigned long))(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"))
SetAssociatedObject(someObject, constVoidPointer, someValue, 1)
}
function getAssociatedObject(someObject, constVoidPointer) {
GetAssociatedObject = #encode(id(id, const void*))(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"))
return GetAssociatedObject(someObject, constVoidPointer)
}
It is used like this:
# create void pointer (probably should be a global variable for later retrieval)
voidPtr = new new Type(#encode(const void))
someVar = [[NSObject alloc] init]
setAssociatedObject(someVar, #[#"hello", #"world"], voidPtr)
getAssociatedObject(someVar, voidPtr)
# spits out #["Hello", "World"]

Related

std.json.parse and memory management

I have the following zig code (simplified):
const allocator = ...;
const Entry = struct {
name: []u8,
};
fn list() ![]u8 {
var entries = try std.json.parse([]Entry, ...);
defer std.json.parseFree([]Entry, entries, ...);
return entries[0];
}
fn main() !void {
const e = try list();
...
}
Everything is (de)allocated with allocator.
I'd like to return entries[0] and recycle everything else. The problem is that parseFree here recycles everything including entries[0] so I can't seemingly use this function.
So what's the most effective way to do that without copying? What if Entry is a big structure and I want to return just one its field, say Entry.name (and, again, recycle everything else)?
The quickest way of achieving what you want is to not use parseFree but instead:
const first = entries[0].name;
for (entries[1..entries.len]) |e| alloc.free(e.name); // frees individual strings
alloc.free(entries); // frees the array of structs
return Entry { .name = first };
This is fairly straightforward but relies on understanding how memory is allocated by std.json and the implementation might one day want to allocate things differently, causing the code above to break.
Because of that, my recommendation would be to just copy the string and only resort to this type of extra complexity once you have demonstrated that avoiding that copy brings perceivable benefits.

Saxonica - .NET API - XQuery - XPDY0002: The context item for axis step root/descendant::xxx is absent

I'm getting same error as this question, but with XQuery:
SaxonApiException: The context item for axis step ./CLIENT is absent
When running from the command line, all is good. So I don't think there is a syntax problem with the XQuery itself. I won't post the input file unless needed.
The XQuery is displayed with a Console.WriteLine before the error appears:
----- Start: XQUERY:
(: FLWOR = For Let Where Order-by Return :)
<MyFlightLegs>
{
for $flightLeg in //FlightLeg
where $flightLeg/DepartureAirport = 'OKC' or $flightLeg/ArrivalAirport = 'OKC'
order by $flightLeg/ArrivalDate[1] descending
return $flightLeg
}
</MyFlightLegs>
----- End : XQUERY:
Error evaluating (<MyFlightLegs {for $flightLeg in root/descendant::FlightLeg[DepartureAirport = "OKC" or ArrivalAirport = "OKC"] ... return $flightLeg}/>) on line 4 column 20
XPDY0002: The context item for axis step root/descendant::FlightLeg is absent
I think that like the other question, maybe my input XML file is not properly specified.
I took the samples/cs/ExamplesHE.cs run method of the XQuerytoStream class.
Code there for easy reference is:
public class XQueryToStream : Example
{
public override string testName
{
get { return "XQueryToStream"; }
}
public override void run(Uri samplesDir)
{
Processor processor = new Processor();
XQueryCompiler compiler = processor.NewXQueryCompiler();
compiler.BaseUri = samplesDir.ToString();
compiler.DeclareNamespace("saxon", "http://saxon.sf.net/");
XQueryExecutable exp = compiler.Compile("<saxon:example>{static-base-uri()}</saxon:example>");
XQueryEvaluator eval = exp.Load();
Serializer qout = processor.NewSerializer();
qout.SetOutputProperty(Serializer.METHOD, "xml");
qout.SetOutputProperty(Serializer.INDENT, "yes");
qout.SetOutputStream(new FileStream("testoutput.xml", FileMode.Create, FileAccess.Write));
Console.WriteLine("Output written to testoutput.xml");
eval.Run(qout);
}
}
I changed to pass the Xquery file name, the xml file name, and the output file name, and tried to make a static method out of it. (Had success doing the same with the XSLT processor.)
static void DemoXQuery(string xmlInputFilename, string xqueryInputFilename, string outFilename)
{
// Create a Processor instance.
Processor processor = new Processor();
// Load the source document
DocumentBuilder loader = processor.NewDocumentBuilder();
loader.BaseUri = new Uri(xmlInputFilename);
XdmNode indoc = loader.Build(loader.BaseUri);
XQueryCompiler compiler = processor.NewXQueryCompiler();
//BaseUri is inconsistent with Transform= Processor?
//compiler.BaseUri = new Uri(xqueryInputFilename);
//compiler.DeclareNamespace("saxon", "http://saxon.sf.net/");
string xqueryFileContents = File.ReadAllText(xqueryInputFilename);
Console.WriteLine("----- Start: XQUERY:");
Console.WriteLine(xqueryFileContents);
Console.WriteLine("----- End : XQUERY:");
XQueryExecutable exp = compiler.Compile(xqueryFileContents);
XQueryEvaluator eval = exp.Load();
Serializer qout = processor.NewSerializer();
qout.SetOutputProperty(Serializer.METHOD, "xml");
qout.SetOutputProperty(Serializer.INDENT, "yes");
qout.SetOutputStream(new FileStream(outFilename,
FileMode.Create, FileAccess.Write));
eval.Run(qout);
}
Also two questions regarding "BaseURI".
1. Should it be a directory name, or can it be same as the Xquery file name?
2. I get this compile error: "Cannot implicity convert to "System.Uri" to "String".
compiler.BaseUri = new Uri(xqueryInputFilename);
It's exactly the same thing I did for XSLT which worked. But it looks like BaseUri is a string for XQuery, but a real Uri object for XSLT? Any reason for the difference?
You seem to be asking a whole series of separate questions, which are hard to disentangle.
Your C# code appears to be compiling the query
<saxon:example>{static-base-uri()}</saxon:example>
which bears no relationship to the XQuery code you supplied that involves MyFlightLegs.
The MyFlightLegs query uses //FlightLeg and is clearly designed to run against a source document containing a FlightLeg element, but your C# code makes no attempt to supply such a document. You need to add an eval.ContextItem = value statement.
Your second C# fragment creates an input document in the line
XdmNode indoc = loader.Build(loader.BaseUri);
but it doesn't supply it to the query evaluator.
A base URI can be either a directory or a file; resolving relative.xml against file:///my/dir/ gives exactly the same result as resolving it against file:///my/dir/query.xq. By convention, though, the static base URI of the query is the URI of the resource (eg file) containing the source query text.
Yes, there's a lot of inconsistency in the use of strings versus URI objects in the API design. (There's also inconsistency about the spelling of BaseURI versus BaseUri.) Sorry about that; you're just going to have to live with it.
Bottom line solution based on Michael Kay's response; I added this line of code after doing the exp.Load():
eval.ContextItem = indoc;
The indoc object created earlier is what relates to the XML input file to be processed by the XQuery.

Lua package containing subpackages

I have written a number of modules for Lua in C. Each of these contains a Lua userdata type and I load and use them like this:
A = require("A")
B = require("B")
a = A.new(3,{1,2,3})
b1 = B.new(1)
b2 = B.new(2) * b1
Now I would like to put both userdata types in a single shared library AandB that can be used like this
AB = require("AandB")
AB.A.new(3,{1,2,3})
What is a good way to achieve this? Right now my luaopen_* functions look like this
int luaopen_A(lua_State *L) {
luaL_newmetatable(L, A_MT);
luaL_setfuncs(L, A_methods, 0);
luaL_newlib(L, A_functions);
return 1;
};
And is it possible then to still load only part, e.g. like this: A = require("AandB.A")?
require("AandB.A") works if you define luaopen_AandB_A in your C library, which must be called AandB.so.
In general, require replaces dots with underscores when trying C libraries.
One thing you can do is to write a lua script module that pulls in both A and B. You can then require that script from your using code:
-- AandB.lua
return { A = require 'A', B = require 'B' }
If you only want to load part of your module, you can just do:
A = require "AandB".A

Read lua interface

In lua, is there any way to read an interface file to extract name/methods/args?
I have an .idl file like this:
interface
{
name = myInterface,
methods = {
testing = {
resulttype = "double",
args = {{direction = "in",
type = "double"},
}
}
}
This is equal to the code bellow (easier to read):
interface myInterface {
double testing (in double a);
};
I can read file, load as string and parse with gmatch for example to extract information, but is there any easy mode to parse this info?
At the end i want something (a table for example) with the interface name, their methods, result types and args. Just to know the interface that i`m working.
Lua has several facilities to interpret chunks of code. Namely, dofile, loadfile and loadstring. Luckily, your input file is almost valid Lua code (assuming those braces were matched). The only thing that is problematic is interface {.
All of the above functions effectively create a function object with a file's or a string's contents as their code. dofile immediately executes that function, while the others return a function, which you can invoke whenever you like. Therefore, if you're free to change the files, replace interface in the first line with return. Then you can do:
local interface = dofile("input.idl")
And interface will be a nice table, just as you have specified it in the file. If you cannot change those files to your liking, you will have to load the file into the string, perform some string manipulation (specifically, replace the first interface with return) and then use loadstring instead:
io.input("input.idl")
local input = io.read("*all")
input = string.gsub(input, "^interface", "return") -- ^ marks beginning of string
local f = loadstring(input)
local interface = f()
In both cases this is what you will get:
> require"pl.pretty".dump(interface)
{
name = "myInterface",
methods = {
testing = {
args = {
{
type = "double",
direction = "in"
}
},
resulttype = "double"
}
}
}
> print(interface.methods.testing.args[1].type)
double
EDIT:
I just realised, in your example input myInterface is not enclosed in " and therefore not a proper string. Is that also a mistake in your input file or is that what your files actually look like? In the latter case, you would need to change that as well. Lua is not going to complain if it's a name it doesn't know, but you also won't get the field in that case.

Firefox extension javascript module: what happens to unexported symbols?

I'm just starting to write my first FF extension using javascript modules (rather than trying an XPCOM component) but I'm fuzzy on what happens when a jsm is loaded.
Q: Does the file scope act as a closure for non-exported symbols, or are unreferenced symbols simply garbage collected?
For an example, could/should a module be written as follows?
//modules/myModule.js
var EXPORTED_SYMBOLS = [ 'foo', 'bar' ];
var data;
function foo(){
return data;
}
function bar(newData){
data = newData;
}
importing it somewhere else as:
var aNS = {};
Components.utils.import("resource://myext/myModule.js", aNS);
aNS.bar('it works?');
alert(aNS.foo()); //alert: 'it works?'
Even if a module can be written this way, is there a good reason not to?
It acts in closure manner, but only if you're referencing it somewhere. In my extension I have something like:
var EXPORTED_SYMBOLS = ['foo'];
let cacheService = Components.classes["#mozilla.org/network/cache-service;1"]
.getService(Components.interfaces.nsICacheService);
let foo = {
svc : cacheService,
dosomethingwithit : function(){this.svc.somemethod();}
}
So because it is referenced by foo.svc my cacheService is well and alive. If I wasn't referencing it anywhere it would've been garbage collected - which is to no surprise since if it's not used who cares.
But now thinking a bit more about it, I'm just wandering why I did it this way. Doesn't really makes much sense, or difference. I could've had something like:
var EXPORTED_SYMBOLS = ['foo'];
function something(){
this.svc = Components.classes["#mozilla.org/network/cache-service;1"]
.getService(Components.interfaces.nsICacheService);
}
let foo = new something();
I think I just liked the looks of the first approach more.

Resources