Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

compiler du C avec de l'ObjC ???

12 réponses
Avatar
unbewust
je voudrais utiliser un soft =E9crit en ObjC (seticon pour MacOS X) avec
un wrapper de ce soft =E9crit en C pour Ruby (language de script) et
ainsi b=E9n=E9ficier d'une extension Ruby.

j'ai test=E9 mon C (en "squelette") et aussi seticon en ObjC mais je
n'arrive pas =E0 les compiler ensemble, j'obtiens une "t=E9trachi=E9e"
d'erreurs =E0 cause des @ qui sont dans les .h et autres .m d'ObjC.


j'imagine qu'il y a une directive gcc pour permettre ce mixage ???

pour info j'utilise mkmf de Ruby pour g=E9n=E9rer le Makefile.

ou bien, dois-je compiler s=E9par=E9ment est ajouter apr=E8s coup les .o
d'ObjC dans mon .bundle ???

je ne connais pas du tout ce genre de manip...


si vous avez un peu de lumi=E8re...

Yvon

10 réponses

1 2
Avatar
Pascal Bourguignon
unbewust writes:

je voudrais utiliser un soft écrit en ObjC (seticon pour MacOS X) avec
un wrapper de ce soft écrit en C pour Ruby (language de script) et
ainsi bénéficier d'une extension Ruby.

j'ai testé mon C (en "squelette") et aussi seticon en ObjC mais je
n'arrive pas à les compiler ensemble, j'obtiens une "tétrachiée"
d'erreurs à cause des @ qui sont dans les .h et autres .m d'ObjC.


j'imagine qu'il y a une directive gcc pour permettre ce mixage ???

pour info j'utilise mkmf de Ruby pour générer le Makefile.

ou bien, dois-je compiler séparément est ajouter après coup les .o
d'ObjC dans mon .bundle ???

je ne connais pas du tout ce genre de manip...


si vous avez un peu de lumière...


Contrairement à C++, les fonctions en Objective-C sont des fonctions C
normales. Donc il faut compiler la bibliothèque avec le compilateur
Objective-C, et faire l'édition de lien avec ruby comme si c'était du
C (c'est du C!).

-----(MyObj.m)---------

@implementation MyObj

- myMethod:(int)a
{
return [self ragnagna:(a+1)];
}

@end

id MyObj_myMethod(id obj,int a){
return [obj myMethod:a];
}

------------------------

Compiler avec gcc -objc, dans une bibliothèque ou .o comme ruby le
veux, et dans ruby, appeler la fonction C MyObj_myMethod.



--
__Pascal Bourguignon__ http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

Avatar
unbewust
On 8 août, 22:22, Pascal Bourguignon wrote:

Contrairement à C++, les fonctions en Objective-C sont des fonctions C
normales. Donc il faut compiler la bibliothèque avec le compilateur
Objective-C, et faire l'édition de lien avec ruby comme si c'était du
C (c'est du C!).

-----(MyObj.m)---------

@implementation MyObj

- myMethod:(int)a
{
return [self ragnagna:(a+1)];

}

@end

id MyObj_myMethod(id obj,int a){
return [obj myMethod:a];

}

------------------------

Compiler avec gcc -objc, dans une bibliothèque ou .o comme ruby le
veux, et dans ruby, appeler la fonction C MyObj_myMethod.



OK merci beaucoup pour l'info, je dois donc faire une compil en "deux
passes" la première pour l'ObjC et la seconde, normale pour le C en
omettant pas d'ajouter le/les *.o obtenu(s) dans la première étape...

Avatar
Pascal Bourguignon
unbewust writes:

On 8 août, 22:22, Pascal Bourguignon wrote:

Contrairement à C++, les fonctions en Objective-C sont des fonctions C
normales. Donc il faut compiler la bibliothèque avec le compilateur
Objective-C, et faire l'édition de lien avec ruby comme si c'était du
C (c'est du C!).

-----(MyObj.m)---------

@implementation MyObj

- myMethod:(int)a
{
return [self ragnagna:(a+1)];

}

@end

id MyObj_myMethod(id obj,int a){
return [obj myMethod:a];

}

------------------------

Compiler avec gcc -objc, dans une bibliothèque ou .o comme ruby le
veux, et dans ruby, appeler la fonction C MyObj_myMethod.



OK merci beaucoup pour l'info, je dois donc faire une compil en "deux
passes" la première pour l'ObjC et la seconde, normale pour le C en
omettant pas d'ajouter le/les *.o obtenu(s) dans la première étape...


Non, seulement compiler le .m avec Objective-C, et on obtient un .o
que l'ont peut lier comme si ça avait été un source C.

Par contre ça peut être utile de séparer en deux entêtes l'interface
Objective-C de l'interface C:

------(MyObj.h)------------

@interface MyObj
- myMethod:(int)a;
@end


-----(MyObj_C.h)-----------

extern id MyObj_myMethod(id obj,int a);

---------------------------

comme ça on peut #include <MyObj_C.h> dans les sources C qui utilisent
MyObj. Mais je ne sais pas si tu auras besoin d'un tel entête pour
utiliser MyObj.o avec ruby.


--
__Pascal Bourguignon__ http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.


Avatar
unbewust
On 14 août, 15:29, Pascal Bourguignon wrote:

Compiler avec gcc -objc, dans une bibliothèque ou .o comme ruby le
veux, et dans ruby, appeler la fonction C MyObj_myMethod.


OK merci beaucoup pour l'info, je dois donc faire une compil en "deux
passes" la première pour l'ObjC et la seconde, normale pour le C en
omettant pas d'ajouter le/les *.o obtenu(s) dans la première étape. ..


Non, seulement compiler le .m avec Objective-C, et on obtient un .o
que l'ont peut lier comme si ça avait été un source C.

Par contre ça peut être utile de séparer en deux entêtes l'interf ace
Objective-C de l'interface C:

------(MyObj.h)------------

@interface MyObj
- myMethod:(int)a;
@end

-----(MyObj_C.h)-----------

extern id MyObj_myMethod(id obj,int a);

---------------------------

comme ça on peut #include <MyObj_C.h> dans les sources C qui utilisent
MyObj. Mais je ne sais pas si tu auras besoin d'un tel entête pour
utiliser MyObj.o avec ruby.


oui, oui, j'ai écrit un tel header. MAIS j'ai un pb à la compil côt é C/
Ruby...


alors, je m'explique.

compil ObjC :

echo `gcc -W -Wall -Wextra -I /System/Library/Frameworks/
Foundation.framework/Headers -framework Foundation -ObjC -o MyObj.o
MyObj.m main.m`

=> obligé d'ajouter un main.m ???

mon main.m bidon :
#import "MyObj.h"

int main( void )
{
return 13;
}

avec :
$> MyObj.o

puis :
$> echo $?

j'obtiens bien 13...

compil C extension to Ruby :

mon extconf.rb :

$CFLAGS << " -I /System/Library/Frameworks/Foundation.framework/
Headers "

$LDFLAGS << " -framework Foundation "

extension_name = 'myrobjc'
dir_config(extension_name)
create_makefile(extension_name)

au make :
~/work/C/RObjCC/ext%> make
cc -dynamic -bundle -undefined suppress -flat_namespace -L/opt/local/
lib -framework Foundation -L"/opt/local/lib" -o myrobjc.bundle
MyRObjC.o main.o MyObj.o -lruby -lpthread -ldl -lobjc
/usr/bin/ld: MyObj.o is input for the dynamic link editor, is not
relocatable by the static link editor again
---------------------
*************************************************************************** *************
[...]
collect2: ld returned 1 exit status
make: *** [myrobjc.bundle] Error 1


mon mon ext C pour Ruby :

VALUE cMyRObjC;

VALUE m_roc_version ( VALUE self )
{
char *version = "MyRObjC version 0.0.1";
return rb_str_new2 ( version );
}

VALUE m_ragnagna ( VALUE self, VALUE inData)
{
int cintData = FIX2INT ( inData );
return INT2FIX ( MyObj_myMethod ( cintData ) );
}

void Init_myrobjc ()
{
cMyRObjC = rb_define_module("MyRObjC");
rb_define_module_function(cMyRObjC, "version", m_roc_version, 0);
rb_define_module_function(cMyRObjC, "ragnagna", m_ragnagna, 1);
}


je ne vois pas ce que je peux faire pour inclure le MyObj.o dans mon
bundle, normalement, mon extconf.rb produit un Makefile qui s'occupe
de ça....

peut-être devrais essayer de "bidouiller à la main" le Makefile ???



Avatar
Pascal Bourguignon
unbewust writes:

On 14 août, 15:29, Pascal Bourguignon wrote:

Compiler avec gcc -objc, dans une bibliothèque ou .o comme ruby le
veux, et dans ruby, appeler la fonction C MyObj_myMethod.


OK merci beaucoup pour l'info, je dois donc faire une compil en "deux
passes" la première pour l'ObjC et la seconde, normale pour le C en
omettant pas d'ajouter le/les *.o obtenu(s) dans la première étape...


Non, seulement compiler le .m avec Objective-C, et on obtient un .o
que l'ont peut lier comme si ça avait été un source C.

Par contre ça peut être utile de séparer en deux entêtes l'interface
Objective-C de l'interface C:

------(MyObj.h)------------

@interface MyObj
- myMethod:(int)a;
@end

-----(MyObj_C.h)-----------

extern id MyObj_myMethod(id obj,int a);

---------------------------

comme ça on peut #include <MyObj_C.h> dans les sources C qui utilisent
MyObj. Mais je ne sais pas si tu auras besoin d'un tel entête pour
utiliser MyObj.o avec ruby.


oui, oui, j'ai écrit un tel header. MAIS j'ai un pb à la compil côté C/
Ruby...


alors, je m'explique.

compil ObjC :

echo `gcc -W -Wall -Wextra -I /System/Library/Frameworks/
Foundation.framework/Headers -framework Foundation -ObjC -o MyObj.o
MyObj.m main.m`

=> obligé d'ajouter un main.m ???


Non, quand on compile un module pour en faire un .o, il faut ajouter
l'option -c. Sinon, gcc effectue une édition de lien et produit un
exécutable (pour lequel effectivement il a besoin d'un main).


compil C extension to Ruby :

mon extconf.rb :

$CFLAGS << " -I /System/Library/Frameworks/Foundation.framework/
Headers "

$LDFLAGS << " -framework Foundation "

extension_name = 'myrobjc'
dir_config(extension_name)
create_makefile(extension_name)

au make :
~/work/C/RObjCC/ext%> make
cc -dynamic -bundle -undefined suppress -flat_namespace -L/opt/local/
lib -framework Foundation -L"/opt/local/lib" -o myrobjc.bundle
MyRObjC.o main.o MyObj.o -lruby -lpthread -ldl -lobjc
/usr/bin/ld: MyObj.o is input for the dynamic link editor, is not
relocatable by the static link editor again


En effet, MyObj.o est un exécutable au lieu d'être un module objet.

Utilise:

file MyObj.o

pour voir la différence.


peut-être devrais essayer de "bidouiller à la main" le Makefile ???


Le reste me semble correct.

--
__Pascal Bourguignon__ http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.




Avatar
unbewust
On 14 août, 19:43, Pascal Bourguignon wrote:

En effet, MyObj.o est un exécutable au lieu d'être un module objet.

Utilise:

file MyObj.o

pour voir la différence.

peut-être devrais essayer de "bidouiller à la main" le Makefile ???


Le reste me semble correct.



OK, j'arrive maintenant à compiler et à avoir la méthode objc dans mon
bundle :

myrobjc.bundle:
(__TEXT,__text) section
dyld_stub_binding_helper:
00000b40 mfspr r0,lr
[...]
00000b6c bctr
__dyld_func_lookup:
00000b70 mfspr r0,lr
[...]
00000b8c bctr
_m_roc_version:
00000b90 mfspr r0,lr
[...]
00000bc4 blr
_m_ragnagna:
00000bc8 mfspr r0,lr
[...]
00000c24 lmw r29,0xfff4(r1)
00000c28 blr
_Init_myrobjc:
00000c2c mfspr r0,lr
[...]
00000c9c blr
-[MyObj myMethod:]:
00000ca0 mfspr r0,lr
[...]
00000d08 blr
_MyObj_myMethod:
00000d0c mfspr r0,lr
[...]
00000d68 blr



par contre j'ai un bus error au run :


Cleaning Directory:
+-----------------+
otool_t_v_MyObj.o.txt, otool_t_v_myrobjc.bundle.txt deleted!
MyObj.o, MyRObjC.o deleted!
myrobjc.bundle deleted!
Makefile deleted!

Compiling ObjC files: "MyObj.m"
+-------------------+
powerpc-apple-darwin8-gcc-4.0.1: MyObj.o: No such file or directory
MyObj.m: In function -[MyObj myMethod:]:
MyObj.m:7: warning: MyObj may not respond to -ragnagna:
MyObj.m:7: warning: (Messages without a matching method signature
MyObj.m:7: warning: will be assumed to return id and accept
MyObj.m:7: warning: ... as arguments.)

Compiling and linking C files: "MyRObjC.m"
+----------------------------+
creating Makefile
In file included from /opt/local/lib/ruby/1.8/powerpc-darwin8.9.0/
ruby.h:24,
from MyRObjC.c:10:
/opt/local/lib/ruby/1.8/powerpc-darwin8.9.0/config.h:73:1: warning:
"alloca" redefined
In file included from /usr/include/stdlib.h:66,
from /System/Library/Frameworks/
CoreFoundation.framework/Headers/CoreFoundation.h:24,
from MyRObjC.c:9:
/usr/include/alloca.h:43:1: warning: this is the location of the
previous definition
/usr/bin/ld: warning multiple definitions of symbol _setregid
/opt/local/lib/libruby.dylib(process.o) definition of _setregid
/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/../../../
libpthread.dylib(setregid.So) definition of _setregid
/usr/bin/ld: warning multiple definitions of symbol _setreuid
/opt/local/lib/libruby.dylib(process.o) definition of _setreuid
/usr/lib/gcc/powerpc-apple-darwin8/4.0.1/../../../
libpthread.dylib(setreuid.So) definition of _setreuid
gcc -I. -I/opt/local/lib/ruby/1.8/powerpc-darwin8.9.0 -I/opt/local/lib/
ruby/1.8/powerpc-darwin8.9.0 -I. -O -pipe -I/opt/local/include -fno-
common -O -pipe -I/opt/local/include -fno-common -pipe -fno-common -
I /System/Library/Frameworks/CoreFoundation.framework/Headers -c
MyRObjC.c
cc -dynamic -bundle -undefined suppress -flat_namespace -L/opt/local/
lib -framework CoreFoundation -L"/opt/local/lib" -o myrobjc.bundle
MyRObjC.o MyObj.o -lruby -lpthread -ldl -lobjc


~/work/C/Cext2Ruby/RObjCC/ext%> ./sample.rb

Testing "RObjCC"
+----------------+
version() = MyRObjC version 0.0.1
cinData = 1
./sample.rb:55: [BUG] Bus Error
ruby 1.8.6 (2007-03-13) [powerpc-darwin8.9.0]

zsh: abort ./sample.rb
~/work/C/Cext2Ruby/RObjCC/ext%>


là c'est juste quand j'appelle la méthode ObjC , mon Cext To Ruby :

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sysexits.h>
#include <CoreFoundation/CoreFoundation.h>
#include "ruby.h"


VALUE cMyRObjC;

/*
* Returns the version of this module
*/
VALUE m_roc_version ( VALUE self )
{
char *version = "MyRObjC version 0.0.1";
return rb_str_new2 ( version );
}

/*
* Returns inData + 1
*/
VALUE m_ragnagna ( VALUE self, VALUE inData)
{
int cinData = FIX2INT ( inData );
printf ( "cinData = %dn", cinData );
int coutData = MyObj_myMethod ( cinData ); // <-- bloque là...
printf ( "coutData = %dn", coutData );
return INT2FIX ( coutData );
}

void Init_myrobjc ()
{
cMyRObjC = rb_define_module("MyRObjC");
rb_define_module_function(cMyRObjC, "version", m_roc_version, 0);
rb_define_module_function(cMyRObjC, "ragnagna", m_ragnagna, 1);
}


Bon, en tout cas merci beaucoup, je me suis fait un build.rb qui fait
tout ce qu'il faut dans l'ordre, reste à trouver un moyen de filer ces
directives à mkmf car je dois utiliser un fichier extconf.rb la
distribution se faisant sous RubyForge en gem...

Merci encore !

Yvon


Avatar
unbewust
On 14 août, 15:29, Pascal Bourguignon wrote:
unbewust writes:
On 8 août, 22:22, Pascal Bourguignon wrote:

Contrairement à C++, les fonctions en Objective-C sont des fonctions C
normales. Donc il faut compiler la bibliothèque avec le compilateur
Objective-C, et faire l'édition de lien avec ruby comme si c'était du
C (c'est du C!).

-----(MyObj.m)---------

@implementation MyObj

- myMethod:(int)a
{
return [self ragnagna:(a+1)];

}

@end

id MyObj_myMethod(id obj,int a){
return [obj myMethod:a];

}

------------------------

Compiler avec gcc -objc, dans une bibliothèque ou .o comme ruby le
veux, et dans ruby, appeler la fonction C MyObj_myMethod.


OK merci beaucoup pour l'info, je dois donc faire une compil en "deux
passes" la première pour l'ObjC et la seconde, normale pour le C en
omettant pas d'ajouter le/les *.o obtenu(s) dans la première étape. ..


Non, seulement compiler le .m avec Objective-C, et on obtient un .o
que l'ont peut lier comme si ça avait été un source C.

Par contre ça peut être utile de séparer en deux entêtes l'interf ace
Objective-C de l'interface C:

------(MyObj.h)------------

@interface MyObj
- myMethod:(int)a;
@end

-----(MyObj_C.h)-----------

extern id MyObj_myMethod(id obj,int a);

---------------------------

comme ça on peut #include <MyObj_C.h> dans les sources C qui utilisent
MyObj. Mais je ne sais pas si tu auras besoin d'un tel entête pour
utiliser MyObj.o avec ruby.



QUELQUES Progrès :

Testing "RObjCC"
+--------------+
version() = MyRObjC version 0.0.1
cinData = 1
in "MyObj_myMethod" a = 1
coutData = 0 // ????
ragnagna(1) = 0

appel depuis C :

int cinData = FIX2INT ( inData );
printf ( "cinData = %dn", cinData );
int coutData = MyObj_myMethod ( NULL, cinData );
printf ( "coutData = %dn", coutData );


MyObj.m :
+-------+
#import "MyObj.h"

@implementation MyObj

- myMethod:(int)a
{
printf("in "%s" a = %dn", __func__, a);
return [self ragnagna:(a+1)];
}

@end

id MyObj_myMethod(id obj,int a)
{
printf("in "%s" a = %dn", __func__, a);
return [obj myMethod:a];
}


DONC myMethod n'est pas appellée depuis quand id obj == NULL côté C
+-------------------------------------------------------------------------- -----------------------------
+

MAIS MyObj_myMethod est bien appellée cf. :
in "MyObj_myMethod" a = 1

=> plus de pb d'édition de liens...
c'est déjà ça ;-)



Avatar
Pascal Bourguignon
unbewust writes:
[...]
par contre j'ai un bus error au run :
[...]
Testing "RObjCC"
+----------------+
version() = MyRObjC version 0.0.1
cinData = 1
./sample.rb:55: [BUG] Bus Error
ruby 1.8.6 (2007-03-13) [powerpc-darwin8.9.0]


Ce n'est pas surprenant:

VALUE m_ragnagna ( VALUE self, VALUE inData)
{
int cinData = FIX2INT ( inData );
printf ( "cinData = %dn", cinData );
int coutData = MyObj_myMethod ( cinData ); // <-- bloque là...


Regarde la définition de MyObj_myMethod: elle prend deux arguments,
l'objet de classe MyObj, et le paramètre de type int.


--
__Pascal Bourguignon__ http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

Avatar
Pascal Bourguignon
unbewust writes:
QUELQUES Progrès :

int coutData = MyObj_myMethod ( NULL, cinData );


En effet c'est un peu mieux, mais envoyer des messages à nil ne va pas
faire grand chose...

À un moment ou à un autre, il faudra faire:

myObj=[[MyObj alloc]init];

et passer myObj à MyObj_myMethod...


--
__Pascal Bourguignon__ http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.

Avatar
unbewust
On 15 août, 18:15, Pascal Bourguignon wrote:
unbewust writes:
QUELQUES Progrès :

int coutData = MyObj_myMethod ( NULL, cinData );


En effet c'est un peu mieux, mais envoyer des messages à nil ne va pas
faire grand chose...

À un moment ou à un autre, il faudra faire:

myObj=[[MyObj alloc]init];

et passer myObj à MyObj_myMethod...


ben ça je devrais pouvoir le faire depuis l'ObjC c'est à dire dans
"MyObj_myMethod"

qui deviendrait qqc comme :

id MyObj_myMethod(int a)
{
printf("in "%s" a = %dn", __func__, a);
myObj=[[MyObj alloc]init];
return [myObj myMethod:a];
}


et donc l'alloc-init se ferait côté ObjC et non côté C, où je ne vois
pas comment faire...


1 2