I have a question about syntax of function parameter in Swift.
I want to get message through C based callback function from library, so I make a function with Objective-C as below:
void foo(char *arg) {
NSLog(#"%s", log);
}
Then, I register foo to MainController interface with Objective-C like this.
typedef void (*CB)(char *);
void addFoo(CB func);
...
addFoo(&foo);
The above code is a simplified representation, but it print log for library well.
Now, I have to change the language from Objective-C to Swift. Most of the source code has changed, but for the above function, the log is not output normally.
How can I change?
Please help.
I tried to convert directly. This is code.
typealias CB = (String) -> Void
func addCB(cd: CB) {
// ...
}
func foo(pa: String) {
// ...
}
var fooFuc: CB = foo(pa: )
addCB(cd: fooFuc)
Related
I am using SNMP++ library in my project and everything works fine. However, there is a method where I need to get callback in my .mm file. Now when I am creating a block and passing it to that function as parameter, it throws an error "No matching member function for call to 'get_bulk'". Here is the piece of code:
void(^callbackFunc)(int,Snmp*,Pdu&,SnmpTarget&,void*);
callbackFunc = ^(int i,Snmp* s,Pdu& p,SnmpTarget& t,void* v) {
};
snmp.get_bulk(pdu, *target, l_repeaters, l_repetitions,callbackFunc);
Also, here is the function signature for "get_bulk" function:
int Snmp::get_bulk(Pdu &pdu, // pdu to use
const SnmpTarget &target, // destination target
const int non_repeaters, // number of non repeaters
const int max_reps, // maximum number of repetitions
const snmp_callback callback,// callback to use
const void * callback_data) // callback data
{
pdu.set_type( sNMP_PDU_GETBULK_ASYNC);
return snmp_engine( pdu, non_repeaters, max_reps, target,
callback, callback_data);
}
What should I pass in 'callback' type?This is the typedef for SNMP_callback:
typedef void (*snmp_callback)(int reason, Snmp *session,
Pdu &pdu, SnmpTarget &target, void *data);
I am stuck on this for the past 4-5 hours now and I can't figure out how to resolve this.
Apple's blocks are not convertible to function pointers, as they also contain data (captured variables, etc.) and a reference counting mechanism. You will need to pass a free function, static C++ class member function, or a C++ non-capturing lambda as the callback.
The lambda is the closest syntactically to a block; only non-capturing lambdas are convertible to a function pointer, however, so you will need to do the capturing "by hand" by passing a pointer to a context struct or similar through the void* callback_data argument which presumably is passed through to the callback as void* data.
The lambda will look something like this:
snmp_callback callback =
[](int reason, Snmp *session, Pdu &pdu, SnmpTarget &target, void *data)
{
// context_struct_type* context = static_cast<context_struct_type*>(data);
};
First off, forgive me on the title. Not really sure how to ask this question:
I have an application that I need to convert to a console application (note the application runs fine as a VCL style windows app). The app uses a few 3rd party widgets that have callback functions. However, when I attempt to compile it, I get 'cannot convert ...' errors, like this:
Cannot convert 'void(Tobject *, TErrorEventParams *)' to 'TErrorEvent'
TErrorEvent is defined as:
typedef void __fastcall (__closure* TErrorEvent)(System::TObject* Sender, TErrorEventParams *e);
The line causing the error is:
handler->OnError = errorHandler;
The code for errorHandler is:
void __fastcall errorHandler(System::TObject* Sender, TErrorEventParams *e)
{
memoLine = e->Description;
updateLog();
}
A __closure type is a pointer to a non-static class method. The compiler does not allow you to assign a standalone non-class function where a __closure is expected. It requires a pointer to a method of a class object. Karem's answer shows you one way to accomplish that.
However, there IS a way to use a non-class function, using the helper TMethod struct (which is how a __closure is implemented behind the scenes).
First, add an explicit 'this' parameter to your event handler:
void __fastcall errorHandler(void *This, TObject* Sender, TErrorEventParams *e)
{
memoLine = e->Description;
updateLog();
}
And then assign the event handler like this:
TMethod m;
m.Code = &errorHandler
m.Data = NULL; // any value you want to pass to the 'This' parameter...
handler->OnError = reinterpret_cast<TErrorEvent&>(m);
Have a look at this documentation:
http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Closure
In short:
TErrorEvent is defined as a pointer to a class member function. So errorHandler has to be declared as a class member function.
The implementation could look somewhat like this:
class TMyClass
{
private:
TMyHandler* handler;
void __fastcall errorHandler(System::TObject* Sender, TErrorEventParams *e);
public:
__fastcall TMyClass();
} my_dummy_class;
__fastcall TMyClass::MyClass()
{
//handler has to be created
handler->OnError = errorHandler;
}
void __fastcall TMyClass::errorHandler(System::TObject* Sender, TErrorEventParams *e)
{
memoLine = e->Description;
updateLog();
}
For example:
Production.cpp
int func1()
{
return 7;
}
void func2()
{
printf("func2");
}
void productionCode()
{
int x = func1();
if(x==7) func2();
}
TestProduction.cpp
int func1()
{
return mock().actualCall("func1").
returnIntValue();
}
void setExpFunc1(int x)
{
mock().expectOneCall("func1")
andReturnValue(x);
}
TEST(testGroupSample, testMockFunc1)
{
setExpFunc1(8);
// this will call mock func1()
productionCode();
}
TEST(testGroupSample, testRealFunc2)
{
// this will call real func1()
productionCode();
}
From my understanding, when func1() was mocked, there's no way to test the actual function.
Below sample code is just an idea on what I'm trying to do.
Because I have to test many functions that calls many functions inside.
Sometimes, I don't care on the actual result of those other function so I mocked it, but when I want to test the behavior of the real function when calling inside a function that I'm testing, I cannot do it since that function is already mocked.
Also I hope I can do this without modifying the production code, only the tests code.
No. You mocked using the linker, so, for the whole file context, the real functions do not exist.
You may achieve this by using function pointers (or std::function, …) to set the implementation used by productionCode() at runtime.
Pseudocode
int func1() { /* Production }
int func1_mock() { /* Mock */ }
std::function<int()> impl; // Use a function ptr for C
void productionCode()
{
int x = impl(); // Call current implementation
// ...
}
TEST(...)
{
impl = func1; // Use production code
productionCode();
impl = func1_mock; // Use mock instead
productionCode();
}
Is it possible in Dart to store a callback function with return and argument type information? It appears I can do the following:
class MyClass {
void addCallback( callback( int ) )
{
_callback = callback;
}
var _callback;
}
But I thought it would be nice if _callback wasn't declared as var, and instead had information about its return and argument types. I couldn't find info on this in the docs, anyone know?
Dart 2 supports a function type syntax:
class MyClass {
void addCallback( callback( int ) )
{
_callback = callback;
}
void Function(int) _callback;
}
The Effective Dart Design Guide states that this form is preferred over typedefs.
You can typedef a Function signature like this:
typedef bool Filter(num x);
List<num> filterNumbers(List<num> numbers, Filter filter) {
return numbers.where(filter).toList();
}
For more great information like this, check out this article: https://www.dartlang.org/articles/idiomatic-dart/
I'd like to port this javascript code to dart.
function Beagle() {
this.argv_ = null;
this.io = null;
};
Beagle.prototype.run = function() {
this.io = this.argv_.io.push();
};
runCommandClass(Beagle);
the probleme is
How to create object Beagle
How to create prototype object Beagle.prototype.run
This kind of Js code (function definition and prototype changes) can be ported to a Dart class. You can follow these main rules :
function Xxxx(){/* js code to init */} (pseudo Js class) translates to :
class Xxxx {
/// constructor
Xxxx() {
/* Dart code to init */
}
}
when you have contructor parameters like in function Xxxx(param1, param2){/* js code to init */} you have to create an other constructor with those parameters :
class Xxxx {
/// constructor with parameters
Xxxx(param1, param2) {
/* Dart code to init with param1, param2 */
}
}
Xxxx.prototype.method1 = function(p1, p2, p3){/* js code for method */} are like methods that have to be translated to :
class Xxxx {
// .... other code
/// method
method1(p1, p2, p3) {
/* Dart code */
}
}
To make your code more clear you can also add type annotations on methods and constructors. This is recommanded by the Dart Style Guide.
Type annotations are important documentation for how a library should be used. Annotating the parameter and return types of public methods and functions helps users understand what the API expects and what it provides.
For instance :
class Xxxx {
/// constructor
Xxxx(String param1, int param2) {
/* Dart code to init with param1, param2 */
}
/// method
void method1(num p1, String p2, DateTime p3) {
/* Dart code */
}
}
class Beagle { //
Map argv_;
int io;
Map portInfo;
// could make sense to make this a constructor, that depends how the Terminal class uses it (didn't look)
void run(this.argv_) {
this.portInfo_ = JSON.parse(this.argv_['argString']); // not tested
io = argv_['io'].length;
}
void sendString_(String s) { // no idea what the underlines at the end of argv_, sendString_, ... are for
// ...
}
void onRead_(String s) {}
void onTerminalResize_(int width, int height) {}
void exit(code) {
// ...
}
void close() {
// ...
}
}
var b = new Beagle(); // not translated from the JS source - just added to show how to create a new object from the Beagle class
b.run(argvFromSomewhere);
This includes a some guessing about what the intention of the JavaScript code might be.
I prefer using specific types when porting from JavaScript. It helped me a lot finding bugs and understanding the intention. When I guessed the wrong type I get an exception at runtime, then I can reason about why I got an unexpected type and which of my assumptions were wrong.