Is type assignability too strict in JavaConstant.Dynamic.ofInvocation()? - byte-buddy

I've read Rafael's article and am now doing awful, terrible things with JavaConstant.Dynamic. Mostly I'm getting a feel for how it works.
As part of these horrid experiments, I am turning an array of non-constant things into an array of JavaConstants. Then I'm invoking JavaConstant.Dynamic.ofInvocation(SOME_METHOD_THAT_ACCEPTS_A_VARARGS_OF_THINGS, javaConstantsArray).
So, for example, something like this:
static final JavaConstant toJavaConstant(final Glorp[] glorps) {
final JavaConstant[] javaConstants = new JavaConstant[glorps.length];
for (int i = 0; i < javaConstants.length; i++) {
javaConstants[i] = toJavaConstant(glorps[i]); // another version of this method that works on scalars
}
return JavaConstant.Dynamic.ofInvocation(SOME_METHOD_THAT_ACCEPTS_A_VARARGS_OF_THINGS, javaConstants);
}
ByteBuddy is telling me in the ofInvocation call that one of the JavaConstants in the varargs array I've passed it is not assignable to the parameter type of the SOME_METHOD_THAT_ACCEPTS_A_VARARGS_OF_THINGS. I can understand this, because strictly speaking a variable arity method accepts an array as its last parameter, and a JavaConstant is not an array. But given that the SOME_METHOD_THAT_ACCEPTS_A_VARARGS_OF_THINGS is ultimately resolved via the MethodHandle machinery with all of its argument adaptation and spreading tricks, I wonder: is this proactive assignability check "too much"? Should ByteBuddy take into account the varargs nature of the bootstrap method? Is there some other way to create an array or a list of an arbitrary number of scalar constants as a constant itself?

Yes, this was a bug and it will be fixed in Byte Buddy 1.10.18. Thanks for the patch!

Related

d2: assigning ranges/iterators to array slices

Consider following code:
enum size = 16;
double[size] arr1 = [...];
double[size] arr2 = [...];
process = (double x) { return (x + 1); };
arr2[] = map!(process)(arr1[]); // here
I have trouble converting results of map back to my plain array. Problem applies not only to map, but also to take, repeat and all those fine tools from std.algorithm and std.range that operate on ranges.
On this assignment, I get Error: cannot implicitly convert expression (map(arr1[])) of type Result to double[]. How can I evaluate range to array without using
uint i = 0;
foreach (x; map!(process)(arr1[])) {
arr2[i] = x;
i++;
}
?
Additionally, can someone please explain, why I must call map!(process)(arr1[]) instead of map!(process)(arr1) with static arrays? Shouldn't static arrays be compatible with dynamic for means of iteration, or I don't get something?
Also, it seems that straightforward enumeration syntax foreach (index, item; sequence) does not work for ranges - are there workarounds? I guess the reason is the same as why ranges cannot be assigned to array slices.
Functions such as map and filter return ranges, not arrays, so simply assigning to an array isn't going to work any more than assigning a string to wstring is going to work. They're different types. And for many range-based functions (including map and filter), the ranges they return are actually lazy in order to avoid unnecessary computation, which makes them that much less compatible with an array. The solution is to use std.array.array, which takes a range and creates a dynamic array from it. So, you could do
auto arr = array(map!process(origArray));
However, I would advise not converting a range into an array before you actually need to, since it can result in unnecessary computations, and it means allocating a new array. If you actually need an array, then by all means, use std.array.array to convert the range, but operating on the range can often be more efficient if you don't need an actual array. However, if you want to convert the result to a static array as opposed to a dynamic one, you're probably better off just assigning each element in a loop (and maybe skipping map altogether), since using std.array.array will then have allocated a dynamic array that you won't be using once you've assigned to the static array. It's a waste of memory.
Also, be aware that using static arrays with range-based functions can be risky in that they must slice the static array to get a dynamic array for the range-based functions to process, and if that dynamic array escapes the scope that the static array was declared in, then you're leaking references to data which no longer exists. For example,
auto func()
{
int[5] arr;
return map!process(arr[]);
}
would be very bad. However, as long as you're done using the slice and nothing refers to it anymore (including any ranges that might have been created) before you exit the scope with the static array in it, you should be fine. It is something to be careful of though.
As for the question about having to slice static arrays, you really should ask that as a separate question, but two existing questions that relate to it are this one and this one. What it pretty much comes down to is that IFTI (Implicit Function Template Instantiation) instantiates using the exact type that it's given, and a static array is neither a dynamic array nor a range, so any templated function which specifically requires a dynamic array or a range will fail to compile with a static array. The compiler will implicitly slice static arrays to convert them to dynamic arrays for functions which explicitly take dynamic arrays, but those sort of implicit conversions don't happen with template instantiation, so you must explicitly slice static arrays to pass them to range-based functions.
As for the question about using foreach with indices and ranges, again, you shouldn't be asking multiple questions in the same question. Please post separate questions for each question that you have. What it comes down to though is that
foreach(elem; range)
{
//stuff
}
gets lowered to something close to
for(; !range.empty; range.popFront())
{
auto elem = range.front;
//stuff
}
And that doesn't involve indices at all. It could be change to create an index variable for you, but it doesn't always make sense for ranges to have their index iterating by one like that on every iteration (much as it usually would be fine), and so that hasn't been done. It's simple enough to add your own counter though.
{
size_t i;
foreach(elem; range)
{
//stuff
++i;
}
}
opApply does support using indices with foreach, but it isn't a range, and doesn't work with range-based functions.

cli/c++ increment operator overloading

i have a question regarding operator overloading in cli/c++ environment
static Length^ operator++(Length^ len)
{
Length^ temp = gcnew Length(len->feet, len->inches);
++temp->inches;
temp->feet += temp->inches/temp->inchesPerFoot;
temp->inches %= temp->inchesPerFoot;
return temp;
}
(the code is from ivor horton's book.)
why do we need to declare a new class object (temp) on the heap just to return it?
ive googled for the info on overloading but theres really not much out there and i feel kinda lost.
This is the way operator overloading is implemented in .NET. Overloaded operator is static function, which returns a new instance, instead of changing the current instance. Therefore, post and prefix ++ operators are the same. Most information about operator overloading talks about native C++. You can see .NET specific information, looking for C# samples, for example this: http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx
.NET GC allows to create a lot of lightweight new instances, which are collected automatically. This is why .NET overloaded operators are more simple than in native C++.
Yes, because you're overloading POST-increment operator here. Hence, the original value may be used a lot in the code, copied and stored somewhere else, despite the existance of the new value. Example:
store_length_somewhere( len++ );
While len will be increased, the original value might be stored by the function somewhere else. That means that you might need two different values at the same time. Hence the creation and return of a new value.

Calling a function by name input by user

Is it possible to call a function by name in Objective C? For instance, if I know the name of a function ("foo"), is there any way I can get the pointer to the function using that name and call it? I stumbled across a similar question for python here and it seems it is possible there. I want to take the name of a function as input from the user and call the function. This function does not have to take any arguments.
For Objective-C methods, you can use performSelector… or NSInvocation, e.g.
NSString *methodName = #"doSomething";
[someObj performSelector:NSSelectorFromString(methodName)];
For C functions in dynamic libraries, you can use dlsym(), e.g.
void *dlhandle = dlopen("libsomething.dylib", RTLD_LOCAL);
void (*function)(void) = dlsym(dlhandle, "doSomething");
if (function) {
function();
}
For C functions that were statically linked, not in general. If the corresponding symbol hasn’t been stripped from the binary, you can use dlsym(), e.g.
void (*function)(void) = dlsym(RTLD_SELF, "doSomething");
if (function) {
function();
}
Update: ThomasW wrote a comment pointing to a related question, with an answer by dreamlax which, in turn, contains a link to the POSIX page about dlsym. In that answer, dreamlax notes the following with regard to converting a value returned by dlsym() to a function pointer variable:
The C standard does not actually define behaviour for converting to and from function pointers. Explanations vary as to why; the most common being that not all architectures implement function pointers as simple pointers to data. On some architectures, functions may reside in an entirely different segment of memory that is unaddressable using a pointer to void.
With this in mind, the calls above to dlsym() and the desired function can be made more portable as follows:
void (*function)(void);
*(void **)(&function) = dlsym(dlhandle, "doSomething");
if (function) {
(*function)();
}

std::unique_ptr and pointer-to-pointer

I've been using std::unique_ptr to store some COM resources, and provided a custom deleter function. However, many of the COM functions want pointer-to-pointer. Right now, I'm using the implementation detail of _Myptr, in my compiler. Is it going to break unique_ptr to be accessing this data member directly, or should I store a gajillion temporary pointers to construct unique_ptr rvalues from?
COM objects are reference-countable by their nature, so you shouldn't use anything except reference-counting smart pointers like ATL::CComPtr or _com_ptr_t even if it seems inappropriate for your usecase (I fully understand your concerns, I just think you assign too much weight to them). Both classes are designed to be used in all valid scenarios that arise when COM objects are used, including obtaining the pointer-to-pointer. Yes, that's a bit too much functionality, but if you don't expect any specific negative consequences you can't tolerate you should just use those classes - they are designed exactly for this purpose.
I've had to tackle the same problem not too long ago, and I came up with two different solutions:
The first was a simple wrapper that encapsulated a 'writeable' pointer and could be std::moved into my smart pointer. This is just a little more convenient that using the temp pointers you are mentioning, since you cannot define the type directly at the call-site.
Therefore, I didn't stick with that. So what I did was a Retrieve helper-function that would get the COM function and return my smart-pointer (and do all the temporary pointer stuff internally). Now this trivially works with free-functions that only have a single T** parameter. If you want to use this on something more complex, you can just pass in the call via std::bind and only leave the pointer-to-be-returned free.
I know that this is not directly what you're asking, but I think it's a neat solution to the problem you're having.
As a side note, I'd prefer boost's intrusive_ptr instead of std::unique_ptr, but that's a matter of taste, as always.
Edit: Here's some sample code that's transferred from my version using boost::intrusive_ptr (so it might not work out-of-the box with unique_ptr)
template <class T, class PtrType, class PtrDel>
HRESULT retrieve(T func, std::unique_ptr<PtrType, PtrDel>& ptr)
{
ElementType* raw_ptr=nullptr;
HRESULT result = func(&raw_ptr);
ptr.reset(raw_ptr);
return result;
}
For example, it can be used like this:
std::unique_ptr<IFileDialog, ComDeleter> FileDialog;
/*...*/
using std::bind;
using namespace std::placeholders;
std::unique_ptr<IShellItem, ComDeleter> ShellItem;
HRESULT status = retrieve(bind(&IFileDialog::GetResult, FileDialog, _1), ShellItem);
For bonus points, you can even let retrieve return the unique_ptr instead of taking it by reference. The functor that bind generates should have signature typedefs to derive the pointer type. You can then throw an exception if you get a bad HRESULT.
C++0x smart pointers have a portable way to get at the raw pointer container .get() or release it entirely with .release(). You could also always use &(*ptr) but that is less idiomatic.
If you want to use smart pointers to manage the lifetime of an object, but still need raw pointers to use a library which doesn't support smart pointers (including standard c library) you can use those functions to most conveniently get at the raw pointers.
Remember, you still need to keep the smart pointer around for the duration you want the object to live (so be aware of its lifetime).
Something like:
call_com_function( &my_uniq_ptr.get() ); // will work fine
return &my_localscope_uniq_ptr.get(); // will not
return &my_member_uniq_ptr.get(); // might, if *this will be around for the duration, etc..
Note: this is just a general answer to your question. How to best use COM is a separate issue and sharptooth may very well be correct.
Use a helper function like this.
template< class T >
T*& getPointerRef ( std::unique_ptr<T> & ptr )
{
struct Twin : public std::unique_ptr<T>::_Mybase {};
Twin * twin = (Twin*)( &ptr );
return twin->_Myptr;
}
check the implementation
int wmain ( int argc, wchar_t argv[] )
{
std::unique_ptr<char> charPtr ( new char[25] );
delete getPointerRef(charPtr);
getPointerRef(charPtr) = 0;
return charPtr.get() != 0;
}

Forwarding method calls to a method with a different signature in Objective-C?

I am trying to implement a JSON-RPC solution, using a server connector object which obtains a list of available functions from a server somehow like
NSDictionary *functions = [server
callJSONFunction: #"exposedFunctions" arguments: nil];
which is a simplified description, since callJSONFunction actually triggers an asynchronous NSURLConnection.
An element of the function list consists of a string describing the objective c selector, the original function name which will be called using the mechanism mentioned above, the function signature and an optional array of argument names.
So for example a function list could look like this:
(
#"someFunctionWithArgumentOne:argumentTwo:" =
{
signature = #"##:##",
functionName = #"someFunction",
arguments = ( #"arg_one", #"arg_two" )
},
#"anotherFunction" =
{
signature = #"##:",
functionName = #"anotherFunction"
}
)
As soon as the function list was successfully retrieved, the selectors are added to the server connector instance using class_addMethod in a loop:
for ( NSString *selectorName in functions ) {
SEL aSelector = NSSelectorFromString ( selName );
IMP methodIMP = class_getMethodImplementation (
[ self class ], #selector ( callerMethod: ) );
class_addMethod ( [ self class ], aSelector, methodIMP, "v#:####" );
}
where callerMethod: is a wrapper function used to compose the actual request, consisting of the function name as a NSString and an NSDictionary of the form
{ #"argument1_name" = arg1, #"argument2_name" = arg2, ... }
hence the signature "v#:##". The callerMethod then invokes callJSONFunction on the server.
After this exhausting introduction (my bad, I just did not know, how to shorten it) I'll finally get to the point: to cover the possibility of different numbers of arguments,
I defined the callerMethod like
- (void) callerMethod: (id)argument, ... { }
wherein I use the va_* macros from stdarg.h to obtain the passed arguments. But when I test the mechanism by invoking
[serverConnector someFunctionWithArgumentOne: #"Argument 1"
argumentTwo: #"Argument 2" ];
the first argument returned by id arg = va_arg ( list, id); is always #"Argument 2"!
I'd really appreciate all theories and explanations on why that happens. This thing is really driving me nuts!
Var-args do not map to regular argument passing quite so neatly. Encoding of arguments is actually quite architecture specific and rife with highly entertaining details that sometime seem like they are self-conflicting (until you discover the note about the one exception to the rule that makes the whole thing coherent). If you really want a good read [sarcasm intended], go have a look at how ppc64 handles long doubles sometime; there are cases where half of the double will be in a register and the other half on the stack. Whee!
The above long, and slightly frothy due to scarring, paragraph is to say that you can't transparently forward a call from one function to another where the two functions take different arguments. Since an Objective-C method is really just a function, the same holds true for methods.
Instead, use NSInvocation as it is designed to hide all of the esoteric details of argument encoding that comprises any given platforms ABI.
In your case, though, you might be able to get away with class_addMethod() by defining a set of functions that define all possible combinations of argumentation. You don't even really need to make a dictionary as you can use the dlsym() function to look up the correct function. I.e.
id trampolineForIdIdSELIdIdInt(id self, SEL _cmd, id obj1, id obj2, int) {
... your magic here ...
}
Then, you could translate the type string "##:##i" into that function name and pass it to dlsym, grab the result and use class_addMethod()....
I do feel an obligation to also mention this book as it is a sort of "whoah... man... if we represent classes as objects called meta classes that are themselves represented as classes then we can, like, redefine the universe as metaclasses and classes" ultimate end of this line of thinking.
Also see this unfinished book by Gregor Kiczales and Andreas Paepcke.