Lua and Objective C not running script - objective-c

I am trying to create an objective c interface that encapsulates the functionality of storing and running a lua script (compiled or not.) My code for the script interface is as follows:
#import <Cocoa/Cocoa.h>
#import "Types.h"
#import "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#interface Script : NSObject<NSCoding> {
#public
s32 size;
s8* data;
BOOL done;
}
#property s32 size;
#property s8* data;
#property BOOL done;
- (id) initWithScript: (u8*)data andSize:(s32)size;
- (id) initFromFile: (const char*)file;
- (void) runWithState: (lua_State*)state;
- (void) encodeWithCoder: (NSCoder*)coder;
- (id) initWithCoder: (NSCoder*)coder;
#end
#import "Script.h"
#implementation Script
#synthesize size;
#synthesize data;
#synthesize done;
- (id) initWithScript: (s8*)d andSize:(s32)s
{
self = [super init];
self->size = s;
self->data = d;
return self;
}
- (id) initFromFile:(const char *)file
{
FILE* p;
p = fopen(file, "rb");
if(p == NULL) return [super init];
fseek(p, 0, SEEK_END);
s32 fs = ftell(p);
rewind(p);
u8* buffer = (u8*)malloc(fs);
fread(buffer, 1, fs, p);
fclose(p);
return [self initWithScript:buffer andSize:size];
}
- (void) runWithState: (lua_State*)state
{
if(luaL_loadbuffer(state, [self data], [self size], "Script") != 0)
{
NSLog(#"Error loading lua chunk.");
return;
}
lua_pcall(state, 0, LUA_MULTRET, 0);
}
- (void) encodeWithCoder: (NSCoder*)coder
{
[coder encodeInt: size forKey: #"Script.size"];
[coder encodeBytes:data length:size forKey:#"Script.data"];
}
- (id) initWithCoder: (NSCoder*)coder
{
self = [super init];
NSUInteger actualSize;
size = [coder decodeIntForKey: #"Script.size"];
data = [[coder decodeBytesForKey:#"Script.data" returnedLength:&actualSize] retain];
return self;
}
#end
Here is the main method:
#import "Script.h"
int main(int argc, char* argv[])
{
Script* script = [[Script alloc] initFromFile:"./test.lua"];
lua_State* state = luaL_newstate();
luaL_openlibs(state);
luaL_dostring(state, "print(_VERSION)");
[script runWithState:state];
luaL_dostring(state, "print(_VERSION)");
lua_close(state);
}
And the lua script is just:
print("O Hai World!")
Loading the file is correct, but I think it messes up at pcall.
Any Help is greatly appreciated.
Heading

Your code is so complex that there are no obvious faults. However, your next step should be to check the return value from lua_pcall. If it is nonzero, there will be an error message on the top of the stack which you can print via
fprintf(stderr, "Pcall failed: %s\n", lua_tostring(state, -1));
If you don't get a useful error message, my next step would be to dump the Lua stack. How many elements are on it? What is the (Lua) type of each element? What is the value. Functions lua_top, and luaL_typename will be useful. To print the value you will have to switch on the results of lua_type. Good luck.

I didn't run your code. But at first glance, I found that the signature of initWithScript: are different between header file (using u8*) and source file (using s8*).

Related

Setting media playback info in MacOs not working

I'm a newbie in ObjC and MacOs development.
My final goal is understand how setting playback info works from ObjC to try to implement that later on Rust (using generated ObjC runtime bindings).
So right now I'm trying to write small piece of code on ObjC that would set playback info (without actually playing anything).
I have found https://github.com/MarshallOfSound/electron-media-service/blob/master/src/darwin/service.mm and used it as a base.
Here's code I have right now:
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <objc/runtime.h>
#include "MediaPlayer/MPNowPlayingInfoCenter.h"
#include "MediaPlayer/MPRemoteCommandCenter.h"
#include "MediaPlayer/MPRemoteCommand.h"
#include "MediaPlayer/MPMediaItem.h"
#include "MediaPlayer/MPRemoteCommandEvent.h"
#interface NativeMediaController : NSObject { }
#end
#implementation NativeMediaController
- (MPRemoteCommandHandlerStatus)remotePlay {
NSLog(#"Play");
return MPRemoteCommandHandlerStatusSuccess;
}
- (MPRemoteCommandHandlerStatus)remotePause {
NSLog(#"Pause");
return MPRemoteCommandHandlerStatusSuccess;
}
- (MPRemoteCommandHandlerStatus)remoteTogglePlayPause {
NSLog(#"PlayPause");
return MPRemoteCommandHandlerStatusSuccess;
}
- (MPRemoteCommandHandlerStatus)remoteNext {
NSLog(#"Next");
return MPRemoteCommandHandlerStatusSuccess;
}
- (MPRemoteCommandHandlerStatus)remotePrev {
NSLog(#"Previous");
return MPRemoteCommandHandlerStatusSuccess;
}
- (MPRemoteCommandHandlerStatus)remoteChangePlaybackPosition:(MPChangePlaybackPositionCommandEvent*)event {
NSLog(#"ChangePlaybackPosition");
return MPRemoteCommandHandlerStatusSuccess;
}
- (MPRemoteCommandHandlerStatus)move:(MPChangePlaybackPositionCommandEvent*)event {
NSLog(#"Move");
return MPRemoteCommandHandlerStatusSuccess;
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Hello, World!");
NativeMediaController* controller = [[NativeMediaController alloc] init];
MPRemoteCommandCenter *remoteCommandCenter = [MPRemoteCommandCenter sharedCommandCenter];
[remoteCommandCenter playCommand].enabled = true;
[remoteCommandCenter pauseCommand].enabled = true;
[remoteCommandCenter togglePlayPauseCommand].enabled = true;
[remoteCommandCenter changePlaybackPositionCommand].enabled = true;
[remoteCommandCenter nextTrackCommand].enabled = true;
[remoteCommandCenter previousTrackCommand].enabled = true;
[[remoteCommandCenter playCommand] addTarget:controller action:#selector(remotePlay)];
[[remoteCommandCenter pauseCommand] addTarget:controller action:#selector(remotePause)];
[[remoteCommandCenter togglePlayPauseCommand] addTarget:controller action:#selector(remoteTogglePlayPause)];
[[remoteCommandCenter changePlaybackPositionCommand] addTarget:controller action:#selector(remoteChangePlaybackPosition:)];
[[remoteCommandCenter nextTrackCommand] addTarget:controller action:#selector(remoteNext)];
[[remoteCommandCenter previousTrackCommand] addTarget:controller action:#selector(remotePrev)];
NSMutableDictionary *songInfo = [[NSMutableDictionary alloc] init];
[songInfo setObject:[NSString stringWithUTF8String:"Test title"] forKey:MPMediaItemPropertyTitle];
[songInfo setObject:[NSString stringWithUTF8String:"Test artist"] forKey:MPMediaItemPropertyArtist];
[songInfo setObject:[NSString stringWithUTF8String:"Test albumtitle"] forKey:MPMediaItemPropertyAlbumTitle];
[songInfo setObject:[NSNumber numberWithFloat:60.0] forKey:MPNowPlayingInfoPropertyElapsedPlaybackTime];
[songInfo setObject:[NSNumber numberWithFloat:360.0] forKey:MPMediaItemPropertyPlaybackDuration];
[songInfo setObject:[NSNumber numberWithFloat:112233] forKey:MPMediaItemPropertyPersistentID];
[MPNowPlayingInfoCenter defaultCenter].playbackState = MPNowPlayingPlaybackStatePlaying;
[[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:songInfo];
NSLog(#"End!");
char input[50] = {0};
printf("Enter anything to quit: ");
scanf("%s", input);
}
return 0;
}
When this code is executed I see no effect in MacOs playing info widget.
Unfortunately right now I have no idea how to debug this or where can I find better ObjC example.
Finally, I found the reason that caused my problem playing with Apple Swift example.
There're two requirements to show playback widget (i didn't find them documented anywhere) that have been missing:
You should register a callback for at least one action (play, pause)
You should build your application as an App, not as Console. If your program is not shown in the dock as a running app - the playback widget wouldn't work.

New in Objective C. Simple bug at runtime. Thread 1: breakpoint 1.1

I am learning Objective C and I have tried to override my superclass (NSObject) description method in my BNRItem class. Though it seems like I have done everything right, my NSLog does not seem to use my overridden description method. Instead I see a Thread 1 Breakpoint 1.1 in my definition of the description method and more precisely, where I defined the descriptionString.
Here is my console output.
2015-08-30 20:49:00.622 RandomItems[46034:1002101] Zero
2015-08-30 20:49:00.623 RandomItems[46034:1002101] One
2015-08-30 20:49:00.623 RandomItems[46034:1002101] Two
2015-08-30 20:49:00.623 RandomItems[46034:1002101] Three
(lldb)
My main.m file:
#import <Foundation/Foundation.h>
#import "BNRItem.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
// Create a mutable array object, store its address in items variable...
NSMutableArray *items = [[NSMutableArray alloc] init];
//Send the message addObject: to the NSMutableArray pointed
//by the variable item, passing a string each time
[items addObject:#"One"];
[items addObject: #"Two"];
[items addObject: #"Three"];
// Send another message, insertObject:atIndex;, to that same array object
[items insertObject:#"Zero" atIndex:0];
// For every item in the items array ...
for (NSString *item in items){
//Log the description of item
NSLog(#"%#", item);
}
// Create a BNRItem instance and log its instance variables in the console
BNRItem *item = [[BNRItem alloc] init];
// Set item name to Red Sofa
item.itemName = #"Red Sofa";
item.serialNumber= #"A1B2C";
item.valueInDollards = 100;
//
NSLog(#"%#", item);
//Destroy the mutable array object
items = nil ;
}
return 0;
}
My header file:
#import <Foundation/Foundation.h>
#interface BNRItem : NSObject
{
NSString *_itemName;
NSString *_serialNumber;
int _valueInDollards;
NSDate *_dateCreated;
}
- (void)setItemName:(NSString *)str;
- (NSString *)itemName;
- (void)setSerialNumber:(NSString *)str;
- (NSString *)serialNumber;
- (void)setValueInDollards:(int)v;
- (int)valueInDollards;
- (NSDate *)dateCreated;
#end
And finally, my implementation file:
#import "BNRItem.h"
#implementation BNRItem
- (void)setItemName:(NSString *)str
{
_itemName = str;
}
- (NSString *)itemName
{
return _itemName;
}
- (void)setSerialNumber:(NSString *)str
{
_serialNumber = str;
}
- (NSString *)serialNumber
{
return _serialNumber;
}
- ( void )setValueInDollards:(int)v
{
_valueInDollards = v;
}
- ( int )valueInDollards
{
return _valueInDollards;
}
-( NSDate * )dateCreated
{
return _dateCreated;
}
- ( NSString * )description
{
NSString *descriptionString = [[NSString alloc] initWithFormat:#"%# (%#): Worth %d, recorded on %#", self.itemName, self.serialNumber, self.valueInDollards, self.dateCreated];
return descriptionString;
}
#end
It sounds like you have simply set a breakpoint on a line in your -description method. The debugger is stopping your program at the breakpoint. There's no indication of an actual error.
If you hit the continue button in Xcode, your program would probably proceed just fine.
You can disable the breakpoint, tell Xcode to ignore all breakpoints, or delete the breakpoint if you don't want to break there. The breakpoint will look like a blue arrow in the margins to the left of your code. Right-click or Control-click on it to see options.
To make Xcode ignore breakpoints, toggle the breakpoint button in the debugging toolbar. It also looks like a right-pointing arrow. It will be filled in blue if breakpoints are enabled. It will be an outline if they're disabled.

EXC_BAD_ACCESS when init a struct

I'm developing an app in Objective-C/OSX (first try). I had a struct (NSDevice custom type) which need to be accessed as a public/extern variable to allow the different interface of the class to access it.
Here is the declaration in the header.
struct NSDevice{
LIBMTP_raw_device_t * usbrawdevice;
int numusbrawdevice;
uint32_t rawdeviceID;
LIBMTP_mtpdevice_t *device;
};
extern struct NSDevice *Device;
#interface DeviceManager : NSObject
- (void) openDevice;
- (void) closeDevice;
#end
and how I implement it in the source file
#import "DeviceManager.h"
struct NSDevice *Device = NULL;
#implementation DeviceManager
- (id)init{
self = [super init];
if(self){
NSLog(#"Init");
LIBMTP_Init();
Device->device = NULL;
Device->numusbrawdevice = 0;
Device->rawdeviceID = 0;
Device->usbrawdevice = NULL;
}
return self;
}
- (NSMtp_error) openDevice {
LIBMTP_error_number_t error = LIBMTP_ERROR_GENERAL;
NSLog(#"Opening Device");
error = LIBMTP_Detect_Raw_Devices(&Device->usbrawdevice, &Device->numusbrawdevice);
When trying to init the struct in the init interface, I got an EXC_BAD_ACCESS. Any idea ?
Can I use the "struct" or is there a better way in Objective-C ?
Thx
Seb, you need to allocate the space for Device.
Try doing this:
- (id)init{
self = [super init];
if(self){
NSLog(#"Init");
LIBMTP_Init();
Device = malloc(sizeof(NSDevice));
Device->device = NULL;
Device->numusbrawdevice = 0;
Device->rawdeviceID = 0;
Device->usbrawdevice = NULL;
}
return self;
}
and declare your structure like this:
typedef struct {
LIBMTP_raw_device_t * usbrawdevice;
int numusbrawdevice;
uint32_t rawdeviceID;
LIBMTP_mtpdevice_t *device;
} NSDevice;
Also, I highly recommend changing the name of NSDevice to SebDevice or something that doesn't start with NS as those prefix characters usually signify something built into the MacOS SDK and it's going to confuse anyone else who has to look at your code after you depart the project.
And one last thing, global variables like this shouldn't start with capital letters. In Objective-C, best practice is for variables to start with lower case letters or maybe a g (for global) or an underscore. Change Device to gDevice.

Instance variable value in two objects of the same class (Objective C)

I am new at Objective C and ay programmer's world in general (2 or 3 weeks). Also I am Italian, and so It's quite difficult for me using english and the right terminology.
I created a class: "Mano" (Hand) with its instances and methods: m1 and m2.
My question is: How can I do to read m1 variables value with m2 ?
m1 and m2 have for example "int a; a=0;"
then m1, executing a method, sets a = 10
how can m2 read m1's a? Becouse if m2 simply reads a it reads his own a ... a=0, right?
Sorry again but I don't know how to explain myself better than this!
This was meant to be a simple RPS (Rock Paper Scissors) game just to start learning a little Objective C programming. In the beginning there were two objects m1 and m2 as the “Computer hand m1” and the “Player hand m2”.
Of course as you can see i joined the two methods (computer random number and human number choosing) so that all de job is made by just one object.
When methods were splitted I had problems in the [verdetto] (game results) methods because of m2 (jn my case) were not able to get the right value of the object instance (i needed m1 values) …
and that’s why I asked you my question!
Here you have 0=Rock 1=Scissors 2=Paper
// File main.m
#import <Foundation/Foundation.h>
#import "mano.h"
int main(int argc, const char * argv[])
{
int contatore;
contatore = 1;
#autoreleasepool {
mano *m1;
m1 = [[ mano alloc ] init ];
// mano *m2;
// m2 = [[ mano alloc ] init ];
while (contatore <= 5) {
NSLog(#"\n Partita N. %d", contatore);
contatore++;
[m1 gioco];
[m1 controlloRisultato]; }
// [m1 generatoreRandom] RANDOM NUMBER GENERATOR to let the computer choose
// [m2 scelta numero]here the player was meant to choose bw 0,1,2.
[m1 verdetto]; //game results
}
return 0;
}
// File mano.h
#import <Foundation/Foundation.h>
#interface mano : NSObject {
NSArray *simboli; //Rock Scissors Paper
NSInteger casuale; // Random Number
NSInteger scelta; // Player Number
NSInteger computer; // CPU wins
NSInteger giocatore; // Player Wins
NSInteger pareggi; // Draws
}
- (void) gioco;
- (void) controlloRisultato;
- (void) verdetto;
// - (void) generatoreRandom
// - (void) scelta numero
#end
// File mano.m
#import "mano.h"
#implementation mano
- (id) init {
self = [super init];
casuale = 0;
scelta = 0;
simboli = [ [ NSArray alloc] initWithObjects: #"Sasso",#"Forbici",#"Carta", nil]; //questo va nella init, giustamente, altrimenti non vale per tutti i metodi.
return self; }
- (void) gioco {
scelta =0;
casuale =0;
casuale = arc4random_uniform(3); //il computer sceglie un numero
// L'utente fa la sua scelta qui sotto
do {
NSLog (#"\n \n Inserisci 0 per Sasso, 1 per Forbici, 2 per Carta");
scanf ("%ld", &scelta);
if (scelta >2 || scelta <0) NSLog (#" \n Hai inserito un numero NON VALIDO");
} while (scelta >2 || scelta <0);
}
- (void) controlloRisultato {
NSLog(#"\nIl computer ha scelto: %#", [simboli objectAtIndex:casuale]);
NSLog(#"\nTu hai scelto: %#", [simboli objectAtIndex:scelta ]);
switch (casuale) {
case (0):
if (scelta == 0) {
NSLog (#"\n È un pareggio!");
++pareggi;
break;}
else if (scelta == 1) {
NSLog (#"\n Il Computer Vince!");
++computer;
break;}
else if (scelta == 2) {
NSLog (#"\n Hai vinto!");
++giocatore;
break;}
case (1):
if (scelta == 0) {
NSLog (#"\n Hai Vinto!");
++giocatore;
break;}
else if (scelta == 1) {
NSLog (#"\n È un pareggio!");
++pareggi;
break;}
else if (scelta == 2) {
NSLog (#"\n Il computer Vince!");
++computer;
break; }
case (2):
if (scelta == 0) {
NSLog (#"\n Il computer Vince!");
++computer;
break; }
else if (scelta == 1) {
NSLog (#"\n Hai Vinto!");
++giocatore;
break; }
else if (scelta == 2) {
NSLog (#"\n È un pareggio");
++pareggi;
break;}
break;
default:
break;
}
}
- (void)verdetto {
NSLog(#"\n Vittorie giocatore: %ld", giocatore);
NSLog(#"\n Vittorie computer: %ld", computer);
NSLog(#"\n Pareggi: %ld", pareggi);
if (giocatore > computer) NSLog(#"\n Bravo! Hai vinto tu la partita!");
else NSLog(#"\n Hai perso! Il computer ha vinto la partita");
}
#end
Same as you would if they were not the same kind of object, basically. First, make what you want to read public:
// Hand.h
#import <Foundation/Foundation.h>
#interface Hand : NSObject
// Each hand maintains a value
#property (assign) int a;
// This makes it easy to show two Hands working together...not necesary
- (instancetype)initAsFirst:(BOOL)first;
#end
Then, use a reference to one object from inside the other:
// Hand.m
#import "Hand.h"
#implementation Hand
// To start, some other object will call this with first set to YES.
- (instancetype)initAsFirst:(BOOL)first
{
self = [super init];
if (self) {
if (first) {
// The first Hand will create a second one to demonstrate the difference.
self.a = 0;
[self showHands:[[Hand alloc] initAsFirst:NO]];
} else {
// The second Hand will have a different value to prove that it's different.
self.a = 10;
}
}
return self;
}
- (void)showHands:(Hand *)h
{
// Display both the value of this hand (first) and the one this hand created (second)
NSLog(#"Mine: %d, Other: %d", self.a, h.a);
}
#end
now I have 1 class
#interface mani : NSObject
that maybe could control the game result.
and 2 subclasses:
#interface computer : mani //for random number generator
#interface giocatore : mani //for player choosing number
Now the matter for me is letting the first class (mani) read its subclasses variables, and do what to do to determine who is the winner! Still can't get how it works, and belive me, I am reading forums, and e-books!

How do I watch for file changes on OS X?

I would like to be notified of writes into a given file – without polling, without having to read from the file and without having to monitor the parent directory and watch the file modification time stamps. How do I do that?
I couldn’t find a simple example, so I’m contributing what I came up with for future reference:
#interface FileWatch ()
#property(assign) dispatch_source_t source;
#end
#implementation FileWatch
#synthesize source;
- (id) initWithPath: (NSString*) path targetQueue: (dispatch_queue_t) queue block: (dispatch_block_t) handler
{
self = [super init];
int descriptor = open([path fileSystemRepresentation], O_EVTONLY);
if (descriptor < 0) {
return nil;
}
[self setSource:dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, descriptor, DISPATCH_VNODE_WRITE, queue)];
dispatch_source_set_event_handler(source, handler);
dispatch_source_set_cancel_handler(source, ^{
close(descriptor);
});
dispatch_resume(source);
return self;
}
- (void) dealloc
{
if (source) {
dispatch_source_cancel(source);
dispatch_release(source);
source = NULL;
}
}
#end
From my expericence, in some case files aren't only written but deleted then rewritten (the case for some plist files). Then you have to adapt the code a little bit : calling the method again when the files gets replaced in ordre to keep the monitoring.
- (void) myMonitoringMethodWithPath: :(NSString*) path
__block typeof(self) blockSelf = self;
__block dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fildes, DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE,
queue);
dispatch_source_set_event_handler(source, ^
{
unsigned long flags = dispatch_source_get_data(source);
//Do some stuff
if(flags & DISPATCH_VNODE_DELETE)
{
[blockSelf myMonitoringMethodWithPath:path];
}
});
dispatch_source_set_cancel_handler(source, ^(void)
{
close(fildes);
});
dispatch_resume(source);
}