Argument attribute definition for Qore function implemented via QPP - qore

I'd like to define a CPP __attribute__ for (Qore script) functions implemented in .qpp and preprocessed into plain .cpp.
Qore script class methods may be called from C++ side. In this case an empty function is implemented in QPP class definition and preprocessed in .cpp file. C++ compiler will raise warning messages during compilation. Solution is GNU attribute unused. Is somehow possible to define argument attributes in .qpp ?
MyClass::onAction(int arg0, reference arg1) {
}
Expanded in cpp as:
static QoreValue MyClass_onAction_HashBGD(QoreObject* self, MyClassObject *o, const QoreValueList* args, q_rt_flags_t rtflags, ExceptionSink* xsink)
Note: ScopeGuard.h contains #define UNUSED_VARIABLE __attribute__((unused)) but qpp syntax does not support "normal" C++ usage as argument prefix.
As there are also automatically expanded arguments seems function flag is to be implemented.

I believe this is already implemented; look at the implementation for [doc] in qpp.cpp; if you declare a parameter variable in a qpp file as [doc], it means that no C++ glue for that variable will be generated, and the parameter variable is for documentation only.
Example in QC_StreamWriter.qpp:
nothing StreamWriter::printf(string[doc] fmt, ...) {
sw->f_printf(args, xsink);
}
This generates the following C++ code:
// nothing StreamWriter::printf(string fmt, ...){}
static QoreValue StreamWriter_printf_VsVV(QoreObject* self, StreamWriter* sw, const QoreValueList* args, q_rt_flags_t rtflags, ExceptionSink* xsink) {
# 146 "QC_StreamWriter.qpp"
sw->printf(args, xsink);
return QoreValue();
}
I hope this helps!

Related

Passing string constant or literal to GCC built-ins in Ada

I've use a few intrinsics before with GNAT, but I get an error for __builtin_cpu_is when trying to pass in an Chars_Ptr:
error: parameter to builtin must be a string constant or literal
I also tried plugging the "amd" target parameter in directly, but that didn't work.
with Ada.Text_IO;
with Interfaces.C.Strings;
procedure Intrinsics is
procedure CPU_Init;
pragma Import (Intrinsic, CPU_Init, "__builtin_cpu_init");
function Is_CPU (CPU_Name : Interfaces.C.Strings.chars_ptr) return Interfaces.C.Int;
pragma Import (Intrinsic, Is_CPU, "__builtin_cpu_is");
Target : constant Interfaces.C.Strings.Chars_Ptr := Interfaces.C.Strings.New_String ("amd");
begin
CPU_Init;
-- ERROR from the below line, from Is_CPU
Ada.Text_IO.Put_Line (Interfaces.C.Int'Image (Is_CPU (Target)));
end Intrinsics;
References I've been looking at:
GCC Built-ins
Learn Ada, Interfacing w/ C
I think you hit a (current) limitation in importing GCC intrinsics in Ada programs (at least for version GCC/GNAT FSF 11.2). The best workaround is to wrap the builtin/intrinsic with string literal in a C function and then import that C wrapper function in the Ada program.
The error is thrown by the GCC back-end (see here). The built-in only accepts a string literal. This is not clear from the equivalent C signature of the built-in. The equivalent C signature suggests that any constant pointer-to-char is accepted:
int __builtin_cpu_is (const char *cpuname)
However, a simple test shows that this works:
#include <stdbool.h>
bool is_amd() {
return __builtin_cpu_is("amd") != 0;
}
But this doesn't:
#include <stdbool.h>
bool is_cpu(const char *cpuname) {
return __builtin_cpu_is(cpuname) != 0;
}
During compilation the abstract syntax tree is analyzed and the reference to the built-in is being matched along with the actual parameter that is passed in. This actual parameter must be a string literal (a specific tree node type). The string literal is then parsed/matched by GCC. Upon success, the call to the built-in in the syntax tree is (as a whole) replaced by a comparison (done here).
$ gcc -c is_amd.c --dump-tree-original && cat is_amd.c.005t.original
;; Function is_amd (null)
;; enabled by -tree-original
{
return __cpu_model.__cpu_vendor == 2 ? 1 : 0;
}
Now, it seems that the GNAT front-end is currently unable to generate the exact nodes (or node pattern) in the syntax tree that will match those expected by the built-in parser. This is likely because of the declared signature of the built-in and the fact that Ada makes a clear distinction between string values and string pointers.
The GNAT front-end compares the binding to __builtin_cpu_is with the signature declared internally by the GCC back-end and concludes that the cpuname argument must be a constant pointer-to-string. So, something like this:
function Is_CPU (CPU_Name : access constant String) return Integer;
pragma Import (Intrinsic, Is_CPU, "__builtin_cpu_is");
However, when using this signature, you cannot pass a string literal directly; you must use some indirection:
AMD : aliased constant String := "amd"
and then
Is_CPU (AMD'Access);
This indirection is (as far as I can see) preserved before the GNAT front-end hands over the syntax tree to the GCC back-end; GNAT will not "inline" the string literal (that is: will not remove the indirection; which I guess is actually a good thing as you do not want a constant string to be inlined into function calls in general: multiple functions might reference the string and if the string is very big, the effect of inlining might cause the program size to grow significantly).
On the other hand, if you want to pass a string literal directly in Ada, then you need a signature similar to
function Is_CPU (CPU_Name : String) return Integer;
pragma Import (Intrinsic, Is_CPU, "__builtin_cpu_is");
This signature, however, conflicts with the signature declared by the GCC back-end. Moreover, the GNAT front-end will complain that a string literal cannot be passed-by-copy (something that is likely required for the call to be accepted and recognized by the back-end).
So, I guess some additional logic for handling GCC built-ins with string arguments would have to be added to the GNAT front-end in order for this to work and allow something like this to compile:
function Is_AMD return Boolean is
function Is_CPU (CPU_Name : String) return Integer;
pragma Import (Intrinsic, Is_CPU, "__builtin_cpu_is");
begin
return Is_CPU ("amd") /= 0;
end Is_AMD;
Until then, wrapping the intrinsic with string literal in a separate C function (like the is_amd() example above) and then importing this C wrapper function in the Ada program will be the way to go.
Eric found a working solution:
with Ada.Unchecked_Conversion;
with Ada.Text_IO;
with Interfaces.C.Strings;
procedure Main is
procedure CPU_Init;
pragma Import (Intrinsic, CPU_Init, "__builtin_cpu_init");
function Is_CPU (CPU_Name : Interfaces.C.Strings.chars_ptr) return Integer;
pragma Import (Intrinsic, Is_CPU, "__builtin_cpu_is");
function To_Chars_Ptr is
new Ada.Unchecked_Conversion (String, Interfaces.C.Strings.chars_ptr);
begin
CPU_Init;
Ada.Text_IO.Put_Line (Integer'Image (Is_CPU (To_Chars_Ptr ("intel"))));
end;
How about trying Target as shown below
Target : constant Interfaces.C.Char_Ptr := Interfaces.C.To_C ("amd");

How to retrieve QPair from QVariant?

I'm doing auto data = combobox->currentData().value<QPair>(); but the compiler complains with:
[ 48%] Building CXX object src/CMakeFiles/mudlet.dir/dlgProfilePreferences.cpp.o
/home/vadi/Programs/Mudlet/mudlet/src/dlgProfilePreferences.cpp: In lambda function:
/home/vadi/Programs/Mudlet/mudlet/src/dlgProfilePreferences.cpp:420:81: error: no matching function for call to ‘QVariant::value()’
auto data = script_preview_combobox->currentData().value<QPair>();
^
In file included from /home/vadi/Programs/Qt/5.9/gcc_64/include/QtCore/QVariant:1:0,
from /home/vadi/Programs/Mudlet/mudlet/cmake-build-debug/src/ui_profile_preferences.h:12,
from /home/vadi/Programs/Mudlet/mudlet/src/dlgProfilePreferences.h:27,
from /home/vadi/Programs/Mudlet/mudlet/src/dlgProfilePreferences.cpp:25:
/home/vadi/Programs/Qt/5.9/gcc_64/include/QtCore/qvariant.h:351:14: note: candidate: template<class T> T QVariant::value() const
inline T value() const
^
/home/vadi/Programs/Qt/5.9/gcc_64/include/QtCore/qvariant.h:351:14: note: template argument deduction/substitution failed:
src/CMakeFiles/mudlet.dir/build.make:806: recipe for target 'src/CMakeFiles/mudlet.dir/dlgProfilePreferences.cpp.o' failed
As far as I see, my call is lining up with template<class T> T QVariant::value() - what's wrong?
QPair is a template class and your code for getting the value from the variant does not fully describe the type.
First you need to know what two types your QPair describes. Then you must use the following code to extract it (changing the QString and int to your pairs data types):
auto pair = combobox->currentData().value<QPair<QString, int> >();

Refactoring methods and creating copies with a different name in Pharo Smalltalk?

I am experimenting with refactoring and some custom functionality. Is there a way to copy a method to the same class as the original but under a new name? (essentially creating a really shallow copy) You can do this by hand by editing the method source, but can it be done programatically?
For example:
doMethodName: anArgument
^ anObject doThat with: anArgument
becomes:
doNewMethodName: anArgument
^ anObject doThat with: anArgument
You can compile methods by sending a compile: message to the target class.
retrieve the method
e.g. method := Float>>#cos or method := Float methodNamed: #cos
retrieve the source code
method sourceCode will return the method code as a string
method ast (or method parseTree) will return the code as parsed tree representation
Compile code into a class (optionally with protocol)
TargetClass compile: sourceCode, or
TargetClass compile: sourceCode classified: protocol
So if you have
Something>>doMethodName: anArgument
^ anObject doThat with: anArgument
You can do
code := (Something>>#doMethodName:) sourceCode.
"replace all matches"
newCode := code copyReplaceAll: 'doMethodName:' with: 'doNewMethodName:'.
"or just the first"
newCode := code copyWithRegex: '^doMethodName\:' matchesReplacedWith: 'doNewMethodName:'.
Something compile: newCode.
Using AST
sourceCode returns the code as string, which isn't the nicest to manipulate.
If you just want to change the method name, you can rename it in the AST, e.g.
tree := (Something>>#doMethodName:) parseTree.
tree selector: 'doNewerMethodName:'.
Something compile: tree newSource.

XQuery: using global var in function

I need to use a counter to remember how many node I have dealed with. So I defined a global var $classCounter. For some unknown reasons, I get an error from zorba:
test.xqy>:15,9: error [zerr:XSST0004]: "local:owlClassNameBuilerHelper": function declared nonsequential but has sequential body
I really don't understand what this error means. How to implement a global counter in XQuery?
The whole xqy file is:
declare namespace rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
declare namespace owl="http://www.w3.org/2002/07/owl#";
declare namespace xsd="http://www.w3.org/2001/XMLSchema#";
declare namespace rdfs="http://www.w3.org/2000/01/rdf-schema#";
import module namespace functx="http://www.functx.com";
declare variable $srcDoc:="test_xsd.xml"; (:need to adjust the input XSD file here:)
declare variable $defaultXMLNS:="http://www.test.com#";
declare variable $defaultXMLBase:=$defaultXMLNS;
declare variable $classCounter:=0;
declare function local:owlClassNameBuilerHelper($pnode as node()*)
as xs:string?
{
$classCounter:=classCounter+1;
let $tmp:=""
return
(
"haha"
(:if(functx:if-empty($pnode/#name, "-1")!="-1") (:if the name attr doesn't exist:)
then data($pnode/ancestor::element[1]/#name) (:get the name attr of first ancestor named element:)
else data($pnode/#name):)
)
};
element rdf:RDF
{
namespace {""} {$defaultXMLNS},
namespace {"owl"} {"http://www.w3.org/2002/07/owl#"},
namespace {"xsd"} {"http://www.w3.org/2001/XMLSchema#"},
namespace {"rdfs"} {"http://www.w3.org/2000/01/rdf-schema#"},
attribute xml:base {$defaultXMLBase}
}
command line:
zorba -i -f -q test.xqy
I need to use a counter to remember how many node I have dealed with.
Firstly, XQuery is a functional programming language. That's a completely different processing model: you can't "remember" what you have "dealt with", because there is no memory and no time dimension. Functions are mathematical functions, they can't have side-effects like updating global variables.
Now, the error message suggests to me that the particular XQuery processor you are using (Zorba) has extensions that allow you to depart from the pure functional programming model; but you are using the extensions incorrectly. In particular, if you want a function to have side-effects then you must declare the function as such. You'll have to look in the Zorba documentation for how to do that, because there is no standard.

In boost::python how to wrap an overrideable function which takes a container of pointers to C++ objects and returns a pointer to one of them?

I'm wrapping a C++ framework with boost::python and I need to make a C++ method overrideable in python. This is a hook method, which is needed by the framework and has a default implementation in C++, which iterates through a list (passed as parameter) and performs a choice. The problems arise because the choice is stated by returning a pointer to the chosen element (an iterator, in fact), but I can't find a way to return a C++ pointer as a result of a python function. Can anyone help?
Thanks
This is most certainly doable, but you don't really have enough details. What you really need to do is create a c++ function that calls your python function, proceses the python result and returns a c++ result. To paraphrase (let's assume I have a boost object called func that points to some python function that parses a string and returns an int):
using boost::python;
A* test(const std::string &foo) {
object module = import("mymodule");
object func = module.attr("myfunc");
// alternatively, you could set the function by passing it as an argument
// to a c++ function that you have wrapped
object result = func(foo);
int val = extract<int>(result);
return new A(val); // Assumes that you've wrapped A.
}
// file: https://github.com/layzerar/box2d-py/blob/master/python/world.cpp
struct b2ContactFilter_W: b2ContactFilter, wrapper<b2ContactFilter>
{
bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)
{
override func = this->get_override("ShouldCollide");
if (func)
{
return func(ref(fixtureA), ref(fixtureB)); //ref is boost::ref
}
return b2ContactFilter::ShouldCollide(fixtureA, fixtureB);
}
bool ShouldCollideDefault(b2Fixture* fixtureA, b2Fixture* fixtureB)
{
return b2ContactFilter::ShouldCollide(fixtureA, fixtureB);
}
};
class_<b2ContactFilter_W, boost::noncopyable>("b2ContactFilter")
.def("ShouldCollide", &b2ContactFilter::ShouldCollide, &b2ContactFilter_W::ShouldCollideDefault)
;
Is this what you need ?

Resources