I'm trying to get into objective c, but I don't have a mac so I am trying to get it to work on linux. I found these two articles which talk about compiling objective c on linux: this one and this one
Ok, I forgot to say that I don't want to use gnustep, it seems dead and I don't want all the cocoa framework, just the objective c syntax and the c standard library. But I can't compile any code without gnustep!
If I try to compile this code:
#import <objc/Object.h>
#import <stdio.h>
#interface Number: Object
{
#public
int number;
}
- (void)printNum;
#end
#implementation Number: Object
- (void)printNum
{
printf("%d\n", number);
}
#end
int main(void)
{
Number *myNumber = [Number new]; // equal to [[Number alloc] init]
myNumber->number = 6;
[myNumber printNum];
return 0;
}
I get a segmentation fault, because there's no init nor alloc methods. And if I don't inherit from Object, like so:
#include <stdio.h> // C standard IO library (for printf)
#include <stdlib.h> // C standard library
// Interface
#interface test
-(void)sayHello :(char *)message;
#end
// Implementation
#implementation test
-(void)sayHello :(char *)message {
printf("%s", message);
}
int main(int argc, char *argv[]) {
test *test = [[test alloc] init];
[test sayHello:"Hello world"];
}
I get a Bus error. It seems like the only way to create interfaces and implement them is inheriting from NSObject. How can I fix this?
By the way, I'm using gcc with -lobjc flag (with gobjc)
EDIT: ok, so I have to create a root object myself if I don't want to use a framework. How can I do this? I imagine it's something like malloc and free in the init and release methods, but I'm not sure. How can I do this?
That's not really how Objective C works. You need the runtime, I'm afraid. Many of the good bits of Objective C are about what happens at run- rather than compile-time. If you take away the library, there's not a lot left.
Related
I have an aarch64 library for Linux and I want to use it from within an amd64 Linux install. Currently, I know one method of getting this to work, which is to use the qemu-arm-static binary emulator with an aarch64 executable I compile myself, that calls dlopen on the aarch64 library and uses it.
The annoyance is that integrating the aarch64 executable with my amd64 environment is annoying (eg. let's say, for example, this arm64 library is from an IoT device and decodes a special video file in real time—how am I supposed to use the native libraries on my computer to play it?). I end up using UNIX pipes, but I really dislike this solution.
Is there a way I can use the qemu-arm-static stuff only with the library, so I can have an amd64 executable that directly calls the library? If not, what's the best way to interface between the two architectures? Is it pipes?
The solution that I implemented for this is to use shared memory IPC. This solution is particularly nice since it integrates pretty well with fixed-length C structs, allowing you to simply just use a struct on one end and the other end.
Let's say you have a function with a signature uint32_t so_lib_function_a(uint32_t c[2])
You can write a wrapper function in an amd64 library: uint32_t wrapped_so_lib_function_a(uint32_t c[2]).
Then, you create a shared memory structure:
typedef struct {
uint32_t c[2];
uint32_t ret;
int turn; // turn = 0 means amd64 library, turn = 1 means arm library
} ipc_call_struct;
Initialise a struct like this, and then run shmget(SOME_SHM_KEY, sizeof(ipc_call_struct), IPC_CREAT | 0777);, get the return value from that, and then get a pointer to the shared memory. Then copy the initialised struct into shared memory.
You then run shmget(3) and shmat(3) on the ARM binary side, getting a pointer to the shared memory as well. The ARM binary runs an infinite loop, waiting for its "turn." When turn is set to 1, the amd64 binary will block in a forever loop until the turn is 0. The ARM binary will execute the function, using the shared struct details as parameters and updating the shared memory struct with the return value. Then the ARM library will set the turn to 0 and block until turn is 1 again, which will allow the amd64 binary to do its thing until it's ready to call the ARM function again.
Here is an example (it might not compile yet, but it gives you a general idea):
Our "unknown" library : shared.h
#include <stdint.h>
#define MAGIC_NUMBER 0x44E
uint32_t so_lib_function_a(uint32_t c[2]) {
// Add args and multiplies by MAGIC_NUMBER
uint32_t ret;
for (int i = 0; i < 2; i++) {
ret += c[i];
}
ret *= MAGIC_NUMBER;
return ret;
}
Hooking into the "unknown" library: shared_executor.c
#include <dlfcn.h>
#include <sys/shm.h>
#include <stdint.h>
#define SHM_KEY 22828 // Some random SHM ID
uint32_t (*so_lib_function_a)(uint32_t c[2]);
typedef struct {
uint32_t c[2];
uint32_t ret;
int turn; // turn = 0 means amd64 library, turn = 1 means arm library
} ipc_call_struct;
int main() {
ipc_call_struct *handle;
void *lib_dlopen = dlopen("./shared.so", RTLD_LAZY);
so_lib_function_a = dlsym(lib_dlopen, "so_lib_function_a");
// setup shm
int shm_id = shmget(SHM_KEY, sizeof(ipc_call_struct), IPC_CREAT | 0777);
handle = shmat(shm_id, NULL, 0);
// We expect the handle to already be initialised by the time we get here, so we don't have to do anything
while (true) {
if (handle->turn == 1) { // our turn
handle->ret = so_lib_function_a(handle->c);
handle->turn = 0; // hand off for later
}
}
}
On the amd64 side: shm_shared.h
#include <stdint.h>
#include <sys/shm.h>
typedef struct {
uint32_t c[2];
uint32_t ret;
int turn; // turn = 0 means amd64 library, turn = 1 means arm library
} ipc_call_struct;
#define SHM_KEY 22828 // Some random SHM ID
static ipc_call_struct* handle;
void wrapper_init() {
// setup shm here
int shm_id = shmget(SHM_KEY, sizeof(ipc_call_struct), IPC_CREAT | 0777);
handle = shmat(shm_id, NULL, 0);
// Initialise the handle
// Currently, we don't want to call the ARM library, so the turn is still zero
ipc_call_struct temp_handle = { .c={0}, .ret=0, .turn=0 };
*handle = temp_handle;
// you should be able to fork the ARM binary using "qemu-arm-static" here
// (and add code for that if you'd like)
}
uint32_t wrapped_so_lib_function_a(uint32_t c[2]) {
handle->c = c;
handle->turn = 1; // hand off execution to the ARM librar
while (handle->turn != 0) {} // wait
return handle->ret;
}
Again, there's no guarantee this code even compiles (yet), but just a general idea.
After searching online and on Stackoverflow for a great deal of time, I have come to realize there are not a lot of concrete examples of using hrtimers in the Linux Kernel. Any example I have found is vague and does not explain the functionality of their program or does not explain how the hrtimers are working well enough for me to understand.
I know there is documentation at /include/linux/hrtimer.h, but that documentation is not clear and seems to assume I am already familiar with them.
Can anyone give a basic example of using this timer?
Simple example, callback every 100ms:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
static struct hrtimer test_hrtimer;
static u64 sampling_period_ms = 100; // 100ms
static u32 loop = 0;
static enum hrtimer_restart test_hrtimer_handler(struct hrtimer *timer)
{
pr_info("test_hrtimer_handler: %u\n", ++loop);
hrtimer_forward_now(&test_hrtimer, ms_to_ktime(sampling_period_ms));
return HRTIMER_RESTART;
}
static int __init test_hrtimer_init(void)
{
hrtimer_init(&test_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
test_hrtimer.function = &test_hrtimer_handler;
hrtimer_start(&test_hrtimer, ms_to_ktime(sampling_period_ms), HRTIMER_MODE_REL);
pr_info("init test_hrtimer.\n");
return 0;
}
static void __exit test_hrtimer_exit(void)
{
hrtimer_cancel(&test_hrtimer );
pr_info("exit test_hrtimer.\n");
return;
}
module_init(test_hrtimer_init);
module_exit(test_hrtimer_exit);
MODULE_LICENSE("GPL");
I coded an Arduino project for my son and learned about C in the process. All works fine but after dividing up the code into ten files and grouping the variables into structs in each file I'm not able to solve one wish for clarity. We need to empirically determine the best size of an array for storing and averaging port reads so this is what I want:
struct Alarms {
// Configurable parameters
const unsigned int number_of_reads = 24;
// State variables
int reads[number_of_reads]; // Error: invalid use of non-static data member 'Alarms::num_of_reads'
};
It’s simple but doesn't work. I tried flexible array members until I found that that feature is not supported in C++. Arduino compiles with C++. I tried many examples of the 'struct hack' but they all returned errors like this one:
struct Alarms {
// Configurable parameters
int number_of_reads = 24;
// State variables
int reads[];
} ar;
void setup_alarm() {
ar.reads = malloc(sizeof(int) * ar.number_of_reads); // Error: incompatible types in assignment of 'void*' to 'int [0]'
}
That looked promising but I suspect my ignorance is glowing brightly. Most struct hack examples call for declaring the struct and later initializing the struct variables. I’m hoping to not duplicate the struct.
I considered splitting the struct but that would be error prone and, well, another compile error:
struct Alarms2 {
int reads[ar.num_of_reads]; // Error: array bound is not an integer constant before ']' token
} ar2;
An alternative is to size the array and get the size later but it needs an explanation:
struct Alarms {
// Configurable parameters
int reads[ 24 ]; // Put number of reads to average between brackets
// State variables
int number_of_reads;
};
void setup_alarm() {
ar.number_of_reads = sizeof(ar.reads) / sizeof(ar.reads[0]); // this works
}
Is there a way to work the struct hack or some similar solution in Arduino to like achieve the first example?
The size of the struct must be known at compilation time. Const data types in structs can change per instance of the structure, that is why you are getting the invalid use of non-static data member 'Alarms::num_of_reads' when you try to initialize your array. The best way to solve this is to have an init_alarm and destroy_alarm functions. Like so ...
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_NUM_OF_READS (24)
struct alarm {
// Configurable parameters
const int number_of_reads;
// State variables
int *reads;
};
void init_alarm(struct alarm *alarm)
{
alarm->reads = (int *) malloc(alarm->number_of_reads * sizeof(int));
}
void destroy_alarm(struct alarm *alarm)
{
free(alarm->reads);
}
int main(int argc, char **argv)
{
// When we create our struct, set number_of_reads to default
struct alarm alarm = {.number_of_reads = DEFAULT_NUM_OF_READS, .reads = NULL};
init_alarm(&alarm);
alarm.reads[0] = 13;
alarm.reads[23] = 100;
printf("alarm.reads[0] = %d, alarm.reads[23] = %d\n", alarm.reads[0], alarm.reads[23]);
destroy_alarm(&alarm);
return 0;
}
Note: Inorder to use the designated initializer to initialize a structure you must compile with ANSI (C99) like so ...
gcc --std=c99 test.c -o test
I am tasked with porting a legacy software, to a Managed Language.
A few of the hard-coded calculation models are extremely time consuming to port, without gaining anything in terms of features or performance from a full port.
We decided to make a C++/CLI wrapper instead.
i.e. something like this:
FortranLib.h:
#pragma comment(lib, "fortranlibrary.lib")
extern "C" {
void SUBROUTINENAME(int * param1, int * param2, float * param3, int * returnCode);
}
using namespace System;
namespace FortranlibraryWrapper {
public ref class FortranLib{
public:
enum class ReturnCodes : int{
ok = 0,
//... and so on and so forth
}
ReturnCodes SubRoutineName(int param1, int param2, float param3);
}
}
FortranLib.cpp:
#include "stdafx.h"
#include "FortranLib.h"
namespace FortranlibraryWrapper {
FortranLib::CalculationReturnCodes FortranLib::SubRoutineName(int param1, int param2, float param3)
{
int returnCode = -1;
SUBROUTINENAME( ¶m1, ¶m2, ¶m3, &returnCode);
return (ReturnCodes)returnCode;
}
}
We have in the actual code tried to bound params 1-3 to avoid issues, but apparently we are not good enough, as we recently we saw this type of error come up, in a new test case:
Intel(r) Visual Fortran run-time error
forrtl: severe (408): fort: (3): Subscript #1 of the array ....
This is due to some calculation in the fortran code, that determines an array index. but the calculated index is outside the bounds of the array.
The problem is that the error comes as an error dialogue, and does not raise an exception. We have already tried this:
int returnCode = -1;
try{
SUBROUTINENAME( ¶m1, ¶m2, ¶m3, &returnCode);
}
catch(...)
{
throw gcnew System::Exception("fortran runtime error??");
}
return (ReturnCodes)returnCode;
and found that it does not catch anything..
The new application is intended as a server based service, so I need to somehow capture this error, and log it, and ideally continue the service, and discard the job that caused the failure.
Does anyone know how to accomplish that?
I would prefer not editing the fortran code, and recompiling it, as I am a novice with that language.
I am studying signals from oreilly book. I came across this.
#include <signal.h>
typedef void (*sighandler_t)(int);----> func ptr returns void. uses typedef
sighandler_t signal (int signo, sighandler_t handler);
Later on in code. He just uses
void sigint_handler (int signo)----> normal function returning void
{
}
can typedef be applied on functions
I want to know how it works
can typedef be applied on functions
Yes.....
I want to know how it works
As the example you have read - the syntax is rather obscure (after 25 years of C I still have to think about it), but it is quite straight forward. Passing and storing pointers to functions is greatly simplified if you use typedefs.
I suggest either take a detour and learn about pointers to functions and typedefs of them, or take it as read for now and return to pointers to function later, as you cannot be a C programmer and avoid them.
A signal is just like a interrupt, when it is generated by user level, a call is made to the kernel of the OS and it will action accordingly. To create a signal, here I just show you an example
#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
void sig_handler1(int num)
{
printf("You are here becoz of signal:%d\n",num);
signal(SIGQUIT,SIG_DFL);
}
void sig_handler(int num)
{
printf("\nHi! You are here becz of signal:%d\n",num);
}
int main()
{
signal(SIGINT,sig_handler1);
signal(SIGQUIT,sig_handler);
while(1)
{
printf("Hello\n");
sleep(2);
}
}
after running this code if you will press Ctrl+C then a message will show - "You are here becoz of signal:2" instead of quiting a process as we have changed a signal according to our action. As, Ctrl+C is a maskable signal.
To know more anbout signals and types of signals with examples please follow the link :
http://www.firmcodes.com/signals-in-linux/