This example is a bit harder. The predicate average/3 is defined to take the template average(+Var, :Goal, -Average) , where Goal binds Var and will unify Average with average of the (integer) results.
PlQuery takes the name of a predicate and the 
goal-argument vector as arguments. From this information it deduces the 
arity and locates the predicate. The method PlQuery::next_solution() 
yields
true if there was a solution and false 
otherwise. If the goal yields a Prolog exception, it is mapped into a 
C++ exception. A return to Prolog does an implicit “cut” (PL_cut_query()); 
this can also be done explicitly by the PlQuery::cut() 
method.
PREDICATE(average, 3) /* average(+Templ, :Goal, -Average) */
{ long sum = 0;
  long n = 0;
  PlQuery q("call", PlTermv(A2));
  while( q.next_solution() )
  { sum += A1.as_long();
    n++;
  }
  return A3.unify_float(double(sum) / double(n));
}
?- [user]. |: p(1). |: p(10). |: p(20). |: % user://1 compiled 0.00 sec, 3 clauses true. ?- average(X, p(X), Average). Average = 10.333333333333334.