I am using a 3rd party library that invokes a Core Foundation function.
Since that lib has a bug, passing incorrect values to a CF function, I need to intercept that call to fix the passed values.
How do I hook into the CF function call so that I can look at the passed parameters, change them and then call the actual (original) function?
I have the impression I can get to the actual function with the CFBundleGetFunctionPointerForName, passing CFBundleGetMainBundle()as the first parameter and the name of the CF function as the second parameter.
In my particular case, that would be:
void *p = CFBundleGetFunctionPointerForName (CFBundleGetMainBundle(), "CFRunLoopTimerCreate");
But that returns NULL.
I also tried this:
void *p = CFBundleGetFunctionPointerForName (CFBundleGetBundleWithIdentifier("com.apple.Cocoa"), "CFRunLoopTimerCreate");
That returns a non-null value but it still does not appear to be a pointer I could change but rather the actual starting address of the function's code.
So, how do I get an address of a function pointer to an imported API function that I can save and then change to point to my intercepting function? Or how else could I hook into an imported function?
CFBundleGetFunctionPointerForName will just return the address of a function in a given bundle; this will never let you change the destination of calls to the function. If you really want to do something like that, please refer to Is it possible to hook API calls on Mac OS? Note that this is highly not recommended.
Related
Is it safe to call XGetErrorText from a error handler set by XSetErrorHandler?
E.g.
int errorHandler(Display *dpy, XErrorEvent *err)
{
char buf[BUFLEN];
XGetErrorText(dpy, err->error_code, buf, BUFLEN);
printf("%s\n", buf)
return 0;
}
XSetErrorHandler(errorHandler);
I'm asking because the man page says you should not call any functions (directly or indirectly) on the display that will generate protocol requests but it does not tell if XGetErrorText does.
XGetErrorText doesn't generate any server traffic. It's not supposed to: the server doesn't know your locale, for example, and cannot supply localised messages. XLib can, and indeed does with a couple of local Xrm database lookups.
The source code of XGetErrorText can be viewed e.g. here. We can see that XGetErrorText calls XGetErrorDatabaseText, and this latter function is not even using its dpy parameter.
Each X extension provides its own error-event-to-error-string translation function. This function does accept a dpy parameter, but, just like XGetErrorDatabaseText is not supposed to use it too generate any server traffic. This error-handling function is by default generateed by the XEXT_GENERATE_ERROR_STRING macro here, which just encapsulates another call to XGetErrorDatabaseText.
After doing promisify on a specific function with bluebird - is it possible to get a reference to the original function that was promisified?
Why: I'm using a helper that gets argument names from the function and on promisified functions it gives back (_arg0, _arg1, _arg2), I was hoping it was possible to get the original function signature from somewhere.
No, you can work around it though.
If it is promisified with promisifyAll you can access it without the Async suffix - otherwise, you'd have to do it yourself:
var promisified = Promise.promisify(cbFunction);
promisified.original = cbFunction;
// access as promisified.cbFunction from that point on.
Otherwise, the original function is captured via a closure and you can't reliably access it. In all honesty you probably shouldn't since that'd meddle with minification anyway.
There are lots of gcc attributes one can assign to variables/functions these days. I have gone through the gcc documentation and I haven't found what I am looking for -- or may be I missed it. Hence the question.
What I am looking for is some mechanism when using gcc, that a function 'X' be called when function 'f' enters and function 'Y' be called when function 'f' exits. Basically I have lot of code currently that does following and I am wondering if the LOCK/UNLOCK could be done "automatically" through some kind of attribute.
f() {
LOCK_RESOURCE();
UNLOCK_RESOURCE();
}
You're looking for __attribute__((cleanup)):
The cleanup attribute runs a function when the variable goes out of scope. This attribute can only be applied to auto function scope variables; it may not be applied to parameters or variables with static storage duration. The function must take one parameter, a pointer to a type compatible with the variable. The return value of the function (if any) is ignored.
I am trying to create my first custom function for a Google Spreadsheet in Apps Script and I am having a hard time using the debugger.
I am working on the custom function demo code from the Google documentation and I have set a breakpoint in the custom function drivingDistance(origin, destination) that is used in a cell of my spreadsheet. The problem I have is, that that the debugger shows the parameters that are passed into the function as being undefined. The content of any other variables that are created during execution is displayed correctly though (as long as they do not depend on the input parameters).
Funny thing is that although the input parameters are displayed as undefined, the function's calculations succeed, so this seems to be a debugger issue. Unfortunately this problem prevents me from successfully learning to create and debug own code (as I will have to work with complex input parameters).
I have a feeling that the problem is connected to the server-side execution of Apps Script, so I tried to log the input parameters using the Logger class and I also tried to copy these variables into new local variables. But all I came up with was undefined.
Another strange hint is, that typeof of the parameters returns String. But getting the length of them throws an error and trying to concatenate them with another string returns the string "undefined" (see my screen dump).
I am looking for insights about what is going on here.
The debugger is probably not lying to you - if you launch that function in the debugger, it will have no parameters passed to it. No worries, though, you just need to make sure that you get values to use for debugging. Take a look at How can I test a trigger function in GAS?, which demonstrates techniques that can be applied for custom functions.
Instead of defining an event to pass to the function, you'll want to provide (or retrieve from your spreadsheet) values for the parameters.
function test_drivingDistance() {
// Define a set of test values
var testSet = [[ 'Washington, DC', 'Seattle, WA' ],
[ 'Ottawa, ON', 'Orlando, FL'],
[ 'Paris, France', 'Dakar, Senegal']];
// Run multiple tests
for (var test in testSet) {
Logger.log('Test ' + test + ' = ' + drivingDistance(testSet[test][0],testSet[test][1]));
}
// Get parameters from sheet
var TestFromSheet = drivingDistance(ss.getRange('A1').getValue(),ss.getRange('A2').getValue());
}
You get the idea. You can still set breakpoints inside your function, or use debugger to pause execution.
Edit - examining arguments
What arguments is the custom function receiving when called from a spreadsheet?
You're limited in what you can do to debug this, since the debugger can't be used to examine your custom function when invoked from Sheets, and security limitations on custom functions block Logging. It might be enough to get an understanding of argument passing in general. While javascript functions may have named parameters, all arguments are passed as an Array-like object, called arguments. This custom function will return an array that reports the arguments received. When called from a spreadsheet, each argument will appear in its own cell, starting at the cell you enter the function into:
function testArguments( ) {
var argArray = [];
for (var arg in arguments) {
argArray.push("arguments[" + arg + "] = " + JSON.stringify(arguments[arg]))
}
return argArray;
}
In javascript, there aren't really types like int or float - just Number. Those parameters will show up without quotes on them, and look like numbers. Dates arrive as Date objects, but when printed this way show up as Date-y strings. Strings have quotes.
A custom function never receives a range as an argument; when you provide a range parameter in the spreadsheet, its contents are collected into a one or two-dimensional array, and the array is the argument.
You can use this hack to see the structure of the arguments being sent into the custom function:
function TEST(input) {
return (JSON.stringify(input));
}
The results will show up in your sheet like this:
Good day!
I began writing my own basic JavaScript library for personal use and distribution a few days ago, but I am having trouble with one of the methods, specifically bind().
Within the method itself, this refers to the library, the object.
I went to Google and found function.call(), but it didn't work out the way I planned it--it just executed the function.
If you take a look at another method, each(), you'll see that it uses call() to pass values.
I also tried the following:
f.arguments[0]=this;
My console throws an error, saying it cannot read '0' of "undefined".
I would like to be able to pass this (referencing the library--NOT THE WINDOW) to use it in the event listener.
You can see it starting at line 195 of the JavaScript of this JSFiddle.
Here it is as well:
bind:function(e,f){
if(e.indexOf("on")==0){
e=e.replace("on","");
}
if(typeof f==='function'){
/*Right now, 'this' refers to the library
How can I pass the library to the upcoming eventListener?
*/
//f=f(this); doesn't work
//f.call(this); //doesn't work
//this.target refers to the HTMLElement Object itself, which we are adding the eventListener to
//the outcome I'm looking for is something like this:
/*$('h3').which(0).bind(function({
this.css("color:red");
});*/
//(which() defines which H3 element we're dealing with
//bind is to add an event listener
this.target.addEventListener(e,f,false)
}
return this;
},
Thank you so much for your help, contributors!
If, as per your comments, you don't want to use .bind(), rather than directly passing f to addEventListener() you could pass another function that in turn calls f with .call() or .apply():
if(typeof f==='function'){
var _this = this;
this.target.addEventListener(e,function(event){
f.call(_this, event);
},false)
}
Doing it this way also lets your library do any extra event admin, e.g., pre-processing on the event object to normalise properties that are different for different browsers.
So in this particular case you actually want to call JavaScript's built in bind method that all functions have.
f = f.bind(this);
f will be a new function with it's this argument set to whatever you passed into it.
Replace f=f(this); with f.apply(this);
Look at underscore code, here:
https://github.com/jashkenas/underscore/blob/master/underscore.js#L596