I'm trying to call an objective-C function from a C function but the code keeps crashing in objc_msgSend.
My objective-C class is a singleton and I'm using the following code.
void c_function(int arg0, const char *arg1)
{
[[objc_class instance] testFunction:arg0 Arg1:arg1];
}
The gdb shows the crash is happening when objective-C function is being invoked. How cal I call an objective-C function from within a c function?
Thanks
There's nothing wrong with your code as there are no special rules for calling objc methods from c functions. If there is a crash in objc_msgSend, then refer to http://www.sealiesoftware.com/blog/archive/2008/09/22/objc_explain_So_you_crashed_in_objc_msgSend.html. The same thing would have happened if the objc line was in other objc code -- it's likely you forgot to retain the shared instance of your singleton.
[[objc_class instance] testFunction:arg0 Arg1:arg1];
As you don’t provide further information:
objec_class is an instance, your singleton? And it handles the message instance? …
or
objec_class is really a class, having a class method instance? And this will give you another instance …
In other words, do you really have something like
#interface class2 {
}
-(void) testFunction:(int)count Arg1:(const char *)args;
#end
and
#include "class2.h"
#interface objc_class {
}
-(class2*) instance {
}
-(void) testFunction:(int)count Arg1:(const char *)args;
#end
or
#include "class2.h"
#interface objc_class {
}
+(class2*) instance;
// be aware of the fact, instance (normaly) does not have
// access to any instance variables!
to be included?
Your code doesn’t look like „hey, object(instance) singleton, I tell you to ‘instance’. Then I take your response and give it the message ‘testFunction:Arg1:’ (with some values inserted)”!
(Are you sure you understood objective c?)
Greetings
1:
#interface class2 {
}
-(void) testFunction:(int)count Arg1:(const char *)args;
#end
2:
#include "class2.h"
#interface objc_class {
}
-(class2*) instance;
#end
3:
#include "class2.h"
#interface objc_class {
}
+(class2*) instance; // be aware of the fact, instance (normally) does not
// have access to any instance variables!
Related
I am receiving the following error when trying to call the "talk" function of my DogClass:
'talk' is not a member of _DogFile.
In fact, I have declared the dog file in the _DogFileClass struct,
and in the class_init I am pointing to the talk function.
How can I access the class method from the instance of the class?
I am including the relevant code:
dog.h:
struct _DogFileClass
{
GObjectClass parent_class;
void (*talk)(DogFile *self)
}
void dog_file_talk(DogFile *self);
dog.c
void dog_file_real_talk(DogFile *self);
void dog_file_class_init(DogFileClass *klass)
{
klass->talk = dog_file_real_talk;
}
void dog_file_talk(DogFile *self)
{
g_return_if_false(DOG_IS_FILE);
DogFileClass *klass = DOG_FILE_GET_CLASS(self);
return klass->talk(self);
}
dog_file_real_talk(DogFile *self)
{
printf("WOOF")
}
and in the end I would like to use the talk function, in the following way:
dog->talk(dog);
when dog is a pointer to the DogFile class
and in the end I would like to use the talk function, in the following way: dog->talk(dog); when dog is a pointer to the DogFile class
That’s not possible, because talk is not a member of the DogFile struct. Your code in dog_file_talk() looks correct, so instead of trying to use dog->talk (dog), use dog_file_talk (dog).
I’m afraid that’s the closest you can get to OOP in C with GObject. If you were to have a talk member on the DogFile struct, that pointer would be duplicated for each instance of DogFile, which would prevent it being overrideable by subclasses, as well as being a waste of memory.
If you want more ‘natural’ OOP, use C++ (or a more modern language such as Rust) directly.
Particularly I'm talking about the constructor of this Poco class: Poco.TimerCallback
I would like to use it in legacy C++ code where most of the classes I've written are "static" so that they only contain static methods and no constructors, just because I won't need multiple instances of such objects anyway, and the classes are merely for encapsulation. Well yeah, the Poco guys suggest to add a callback method like this:
TimerCallback<MyClass> callback(*this, &MyClass::onTimer);
timer.start(callback);
Do I understand this code snippet correctly: MyClass::onTimer may also be a static method of MyClass, but I also need the current instance of MyClass, so that methods of static classes, which are not instantiated, are simply banned from being used as a TimerCallback, or am I wrong?
Thank you.
I would not call it "banned" - the function callbacks are just not implemented, and there is nothing preventing you to implement it yourself (and send it back as a contribution, if you are inclined to do so).
I'd just extend the TimerTaskAdapter, so that it does not require object instance, eg. something like this:
typedef void (*FunctionCallback)(TimerTask&);
TimerTaskAdapter(FunctionCallback func): _pObject(0), _method(0), _func(func){}
...
FunctionCallback _func;
Then detect in TimerTaskAdapter::run() what is null and whether to call the method or function:
void run()
{
if (_pObject) (_pObject->*_method)(*this);
else (*_func)(*this);
}
After running into a much more nasty problem (related to pointers to class members) when extending TimerTaskAdapter, someone suggested to derive my class from TimerTask directly: Pointer to member type incompatible with object type → What is the cause?
See this sourcecode:
ProceduralTimerTaskAdapter.h:
// Header file for ProceduralTimerTaskAdapter.cpp class file.
// This is an extension of the Poco::Util::TimerTask class.
#include <Poco/Util/Timer.h>
#include <Poco/Util/TimerTask.h>
#ifndef PROCEDURALTIMERTASKADAPTER_H
#define PROCEDURALTIMERTASKADAPTER_H
using namespace std;
using namespace Poco::Util;
typedef void (*Callback) (TimerTask&);
namespace Poco {
namespace Util {
class ProceduralTimerTaskAdapter : public TimerTask {
public:
ProceduralTimerTaskAdapter (Callback procedure); // Constructor
void run (); // Method defining the main thread
protected:
~ProceduralTimerTaskAdapter (); // Destructor (not for general use)
private:
ProceduralTimerTaskAdapter (); // Default constructor (not for general use)
Callback procedure; // The callback procedure called by the timer.
};
}
}
#endif
ProceduralTimerTaskAdapter.cpp:
// This is the implementation of the ProceduralTimerTaskAdapter class.
#include <iostream>
#include <Poco/Util/Timer.h>
#include <Poco/Util/TimerTask.h>
#include "ProceduralTimerTaskAdapter.h"
using namespace std;
using namespace Poco::Util;
ProceduralTimerTaskAdapter::ProceduralTimerTaskAdapter (Callback proc) :
TimerTask::TimerTask (),
procedure (proc)
{
}
ProceduralTimerTaskAdapter::~ProceduralTimerTaskAdapter ()
{
}
void ProceduralTimerTaskAdapter::run ()
{
procedure (*this);
}
It worked out of the box. Nevertheless thank you for your answers & comments!
From what I've read, "construct-on-first-use" uses a method to create a static variable the first time the method is called, and then just returns the same variable on subsequent method calls. I made this simple C++ program in eclipse:
#include "stdio.h";
class testClass {
public:
testClass() {
printf("constructed\n");
}
~testClass() {
printf("destructed\n");
}
};
testClass test() {
static testClass t;
return t;
}
int main() {
test();
test();
test();
printf("tests done!\n");
}
and here is my result:
constructed
destructed
destructed
destructed
tests done!
destructed
It seems like main creates one instance and then destroys it 4 times. Is this supposed to happen? I thought the destructor should only be called at the end of the program.
I have a suspicion I might have messed up my computer somehow, but I may have just made a simple mistake in my code...any ideas?
Please specify what do you expect from the code.
Since it's a static variable it will be shared between function calls, that's why you see its constructor called just once. You are returning its copy though, that's why you only see destructors after the constructor.
add a copy constructor and you will notice it:
testClass(const testClass& in) { *this = in; printf("copy constructor\n");
normally the compiler should generate the copy constructor if you didn't implement one, it shouldn't be surprising though that it will not print a custom message.
I was reading up about bypassing objective-c's messaging to gain performance (irrelevant to this specific question) when i found an interesting bit of code:
#import <Cocoa/Cocoa.h>
#interface Fib : NSObject { }
- (long long) cFib: (NSUInteger) number;
#end
#implementation Fib
// c implementation of fib
long long cFibIMP(NSUInteger number)
{
return (number < 3) ? 1 : cFib(number - 1) + cFib(number - 2);
}
// method wrapper for c implementation of fib
- (long long) cFib: (NSUInteger) number
{
return cFibIMP(number);
}
#end
My question is; when using c function, within an objective-c object, what scope is the c function (cFibIMP in this particular case) placed in? Does the objective-c class encapsulate the c function removing change of name-clash or is the c function simply dumped into the global scope of the whole objective-c program?
The functions are dumped in the "global" scope.
You can check this by adding a new class at the end of your sample code:
#interface Gib : NSObject {}
#end
#implementation Gib
- (void) t
{
NSLog(#"%d", cFibIMP(10));
}
#end
The C function has global scope.
If you want to have something like "class" scope, your best bet is probably to use the static keyword, which limits the scope of the function to the source file in which it is contained. For the sort of usage you're illustrating here, that's usually close enough.
I am writing an Objective-C class but it uses an API written in C. This is mostly fine as mixing C calls with Objective-C calls causes few problems.
However one of the API call requires a call back method (example):
success = CFHostSetClient(host, MyCFHostClientCallBack, &context);
Where MyCFHostClientCallBack is a C function defined like this:
static void MyCFHostClientCallBack(CFHostRef host, CFHostInfoType typeInfo, const CFStreamError *error, void *info);
Can/How do I call an Objective-C method in place of this?
Can/Should I mix C functions with my Objective-C calls?
How do I mix C functions with Objective-C methods?
Mixing C and Objective-C methods and function is possible, here is a simple example that uses the SQLite API within an iPhone App: (course site)
Download the Zip file (09_MySQLiteTableView.zip)
C functions need to be declared outside of the #implementation in an Objective-C (.m) file.
int MyCFunction(int num, void *data)
{
//code here...
}
#implementation
- (void)MyObjectiveCMethod:(int)number withData:(NSData *)data
{
//code here
}
#end
Because the C function is outside of the #implementation it cannot call methods like
[self doSomething]
and has no access to ivars.
This can be worked around as long as the call-back function takes a userInfo or context type parameter, normally of type void*. This can be used to send any Objective-C object to the C function.
As in the sample code, this can be manipulated with normal Objective-C operations.
In addition please read this answer: Mixing C functions in an Objective-C class
To call Objective-C code from a C callback I would use something like:
void * refToSelf;
int cCallback()
{
[refToSelf someMethod:someArg];
}
#implementation SomeClass
- (id) init
{
self = [super init];
refToSelf = self;
}
- (void) someMethod:(int) someArg
{
}
Can/How do I call an Objective-C method in place of this?
You cannot.
Can/Should I mix C function in with my Objective-C call?
Yes. Write a C function and use that as the callback to the CF function.
How do I mix C function with Objective-C methods?
You can set self as the info pointer in your context structure. That will be passed to the callback. Then, in the callback, cast the info pointer back to id:
MyClass *self = (id)info;
You can then send self messages. You still can't directly access instance variables, though, since a C function is outside of the #implementation section. You'll have to make them properties. You can do this with a class extension. (Contrary to what that document says, you would not declare the extension inside #implementation, but in the same file with it, generally right above it.)
What I've always found helpful in this situation is to make an Obj-C wrapper on top of the C API. Implement what you need to using C functions, and build an Objective-C class (or two) on top of it, so that's all the outside world will see. For example, in the case of a callback like this, you might make a C function that calls Obj-C delegate methods on other objects.
.m call function inside .c:
CrifanLib.h
#ifndef CrifanLib_h
#define CrifanLib_h
#include <stdio.h>
void fileModeToStr(mode_t mode, char * modeStrBuf);
#endif /* CrifanLib_h */
CrifanLib.c
#include "CrifanLib.h"
#include <stdbool.h>
void fileModeToStr(mode_t mode, char * modeStrBuf) {
// buf must have at least 10 bytes
const char chars[] = "rwxrwxrwx";
for (size_t i = 0; i < 9; i++) {
// buf[i] = (mode & (1 << (8-i))) ? chars[i] : '-';
bool hasSetCurBit = mode & (1 << (8-i));
modeStrBuf[i] = hasSetCurBit ? chars[i] : '-';
}
modeStrBuf[9] = '\0';
}
called by Objective-C's .m:
#include “CrifanLib.h"
#interface JailbreakDetectionViewController ()
#end
#implementation JailbreakDetectionViewController
…
char* statToStr(struct stat* statInfo){
char stModeStr[10];
fileModeToStr(statInfo->st_mode, stModeStr);
...
}
...
done.