I am trying to bind some *.framework library which (among others) uses CoreGraphics.
So, the code generated by Sharpie is as follows:
// +(CGImageRef)rotateCGImage:(CGImageRef)image byRadians:(double)radians;
[Static]
[Export ("rotateCGImage:byRadians:")]
unsafe CGImageRef* RotateCGImage (CGImageRef* image, double radians);
However, when trying to build it, I receive error message like "CGImageRef could not be found".
Also, I can't find corresponding class in the list of members of CoreGraphics in Assembly Explorer.
(Same way as using CoreGraphics; doesn't help.)
It looks like this class (or struct) is just not supported by Mono: I just can't find it in regular iOS project libraries neither.
And actually, there is a number of similar "ref-like" classes which are missed: CMSampleBufferRef from Core Media, CVImageBufferRef from Core Video etc.
So, how can I handle this situation?
Please try the solution in this thread:
CGImageRef doesn't exist in Xamarin. In Obj-C, CGImageRef is just a pointer to CGImage, so I would think you could just change all of those CGImageRef to CGImage.
I think it should be something like this:
[Static]
[Export("rotateCGImage:byRadians:")]
unsafe CGImage RotateCGImage(CGImage image, double radians);
The same to other "...Ref" in your project.
From what I've found out (and one of the approaches Xamarin team uses inside of their framework), the solution is as follows:
static extern CGImagePixelFormatInfo CGImageGetPixelFormatInfo (/* __nullable CGImageRef */ IntPtr handle);
static extern IntPtr /* CFStringRef */ CGImageGetUTType (/* __nullable CGImageRef* */ IntPtr image);
So, because of C# managed architecture, there are no explicit pointers to implement, that's why they just didn't create any *Ref-like classes across Mono.
The only thing to point here is that they pass IntPtr for both cases: CGImageRef and CGImageRef*, which has sense of course. However, the trick is in passing the CGImage pointer correctly inside of calling method, because in first case it must be this:
image == null ? IntPtr.Zero : image.Handle
so, passing a pointer of the CGImage. But in second case it must be a pointer to Handle, I assume.
Related
Inside of iOS SDK, lots of constants defined by Apple can be found looking something like this:
extern const CFStringRef kSomeReallyNiceConstant
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_8_0);
If I check for presence of this constant standard way:
if (NULL == &kSomeReallyNiceConstant)
I am pretty much referencing it and in order for my code to compile properly, I need at least iOS SDK 8.0 or higher in this case.
When it comes to objects and methods, reflection approach works nicely with usage of NSClassFromString, respondsToSelector and performSelector.
Is there a chance to use some kind of reflection (access to string constant by name) in attempt to get it's value if it exists (or none if it doesn't)?
I know that I can use macros to check for iOS version and execute different code paths based on that information, but I don't want to use that approach.
I managed to do this with pointer:
#include <dlfcn.h>
// ...
int *pointer = dlsym(RTLD_SELF, "kSomeReallyNiceConstant");
if (pointer) {
NSLog(#"Thing exists!");
} else {
NSLog(#"Nope, doesn't exist!");
}
but I am not sure if this is something that would cause app rejection. Do you maybe know?
Regardless of this pointer approach, I'm curious to hear if there's any other way to achieve this?
Nothing better than suggested solution found on this topic.
#include <dlfcn.h>
// ...
int *pointer = dlsym(RTLD_SELF, "kSomeReallyNiceConstant");
if (pointer) {
NSLog(#"Thing exists!");
} else {
NSLog(#"Nope, doesn't exist!");
}
I faced a problem, that I can't solved for 3 days and you're my last hope.
My goal is to record sound with Bass.dll (there's special version of library for iPhone and version of .net wrapper for it; can be found here: un4seen.com)
On simulator program works (or seems to work properly). But when I tried to run it on the iPhone - I got this error:
"Attempting to JIT compile method '(wrapper native-to-managed) RecordingAudioHelloWorld.Player:recordingHandler (int,intptr,int,intptr)' while running with --aot-only."
error happens here:
RECORDPROC _recordingHandler = new RECORDPROC(recordingHandler);
_record = Bass.BASS_RecordStart(16000, 1, BASSFlag.BASS_SPEAKER_RIGHT, _recordingHandler, IntPtr.Zero); // <-- ERROR!!!
private int recordingHandler (int handle, IntPtr buffer, int length, IntPtr user)
{
//....
}
As I read here, on SO, I changed Linker behavior to "Link SDK assemblies only", but it has no effect.
Is there anything that I could do with it?
Try to add the MonoPInvokeCallback attribute to your recordingHandler function. Note that you also need to make the function static. YourDelegateType should be the delegate type you defined in C# that corresponds to the signature of this method.
[MonoPInvokeCallback (typeof(YourDelegateType)]
private static int recordingHandler (int handle, IntPtr buffer, int length, IntPtr user)
{
// ...
}
I have the following structure that is defined in a header file for a library that a vendor has given to us.
typedef struct {
int iLen;
int iType;
int state;
unsigned char data[1200];
} TCardCmdRespond;
I have created a structure in C# that I think matches it.
[StructLayout(LayoutKind.Sequential)]
public struct TCardCmdRespond
{
public int iLen;
public int iType;
public int state;
public byte[] data;
}
I have a few things to point out here. I am not sure what an unsigned char array should map to. I initially guessed that unsigned char should map to char but char in C# is Unicode so that doesn't seem like it would work. I also tried mapping it to a byte. I also don't know if the length 1200 will be significant to the marshaler and if so, how to designate it.
I have the following method in my monotouch app that takes the structure as a parameter.
[Export("OnRecvData:")]
public void OnRecvData(TCardCmdRespond respond)
{
...
}
The method is invoked by the library via a selector. The method is invoked without a problem. The problem arises when I look at the data contained in the structure. The numbers are extremely high when I am expecting them to be in the range between 1-3 (comparable objective-c code shows the iType to be in this range). I have tried using bit-converter to reverse the byte order in case it is an endianness problem that the marshaler didn't solve for me. The numbers are still high so I think the problem goes beyond simple endianness.
Further problems arise when I try to pull the data out of the char array. It isn't null but trying to access it in any way beyond a null check crashes the application with an EXC_BAD_ACCESS (SIGABRT)
My workaround solution is to write a wrapper for this in objective-c that breaks the structure apart into parameters instead. Then create a library that wraps it up and bind that instead. My objective-c skills are not so hot and that is a slow process however.
Is there a way that I can make this work without having to wrap this up in an objective-c library?
Your C# definition is incorrect.
The C version includes an inline block of 1200 bytes for the array, while your C# version contains a pointer to an array (4 bytes).
You can look at this:
http://msdn.microsoft.com/en-us/library/z6cfh6e6.aspx
Apologies if this is too vague... this is my first post here and I'm well and truly stumped on this issue!
I've been attempting to transition an iOS Xcode project using Audio Units to ARC, but it appears to have broken the functionality of the audio unit processing class. Some symptoms... When I attempt referencing 'self' in AUProcessor.mm, the AUProcessor class is referred to as 'const*', whereas in the pre-ARC version, there was no 'const*' mentioned.
This pointer to 'self' produces the following error:
callbackStruct.inputProcRefCon = self;
[error] Assigning to 'void *' from incompatible type 'AUProcessor *const __strong'.
I can remove the error by adding (__bridge void*) ahead of self, which allows the project to compile. However, the Audio Unit processor doesn't work in the app.
I can't see anything elsewhere in the code that is significantly different from the pre-ARC version in terms of how the class is referenced.
Let me know if more context is required.
Thanks in advance!!
(BTW, thank you to all contributors to these forums... they are truly a wonderful resource for keen yet inexperienced programmers!)
Typically, (__bridge void*) would be the correct cast here. This means "take a pointer to this object without applying any memory management; I promise I'll hold onto it for as long as it's needed." (That last part is just implied, but if you don't, you'll crash.)
Are you certain that self continues to exist for as long as this audio unit? If nothing has a strong reference to self, then it will disappear and inputProcRefCon will become a dangling pointer.
When you say "doesn't work in the app," what do you mean? Does it crash? Does the callback not happen? When the callback happens, does it not have the right data?
I managed to resolve my issue by excluding the troublesome class from ARC using the compiler flag -fno-objc-arc.
Its not a very satisfying conclusion but at least my app is working again... Looks like I'm going to need to learn more about memory management!
The code below is working for me with the MusicPlayer API. I don't know that it is correct but I am not getting any errors or memory leaks. Hope it helps!
// assign the callback:
MusicSequenceSetUserCallback( sequence, MyEventCallback, (__bridge_retained void *)self );
//the callback method:
void MyEventCallback(void *inClientData,
MusicSequence inSequence,
MusicTrack inTrack,
MusicTimeStamp inEventTime,
const MusicEventUserData *inEventData,
MusicTimeStamp inStartSliceBeat,
MusicTimeStamp inEndSliceBeat)
{
struct MyMusicEventUserData* userEventData = ( MyMusicEventUserData *)inEventData;
[(__bridge MusicPlayerController*)inClientData MIDIEvent:userEventData
eventTime:inEventTime
startSliceBeat:inStartSliceBeat
endSliceBeat:inEndSliceBeat];
}
What is a good way to load a GLSL shader using C/C++ without using Objective-C or any Apple APIs?
I am currently using the following method, which is from the iPhone 3D Programming book, but it says that it is not recommended for production code:
Simple.vsh
const char* SimpleVertexShader = STRINGIFY
(
// Shader code...
);
RenderingEngine.cpp
#define STRINGIFY(A) #A
#include "Simple.vsh"
// ...
glShaderSource( shaderHandle, 1, &SimpleVertexShader, 0 );
If you want to load your shaders from files in your app bundle, you can get the file paths using the NSBundle object (in Objective-C), or using the CoreFoundation CFBundle object (in pure C).
Either way, you are using Apple-specific APIs. The only thing you're getting by using CFBundle instead of NSBundle is more boilerplate code.
If you don't want to use any Apple APIs, then your options are to embed your shaders as literal strings, or connect to a server on the Internet and download them (using the Unix socket API).
What you really need to do is define an interface by which your RenderingEngine gets the source code for its shaders, and implement that interface using the appropriate platform-specific API on each platform to which your port the RenderingEngine. The interface can be something super simple like this:
RenderingEngineShaderSourceInterface.h
#ifdef __cplusplus
extern "C" {
#endif
// You are responsible for freeing the C string that this function returns.
extern char const *RenderingEngine_shaderSourceForName(char const *name);
#ifdef __cplusplus
}
#endif
Then you create RenderingEngineShaderSource_Windows.cpp, RenderingEngineShaderSource_iOS.m, RenderingEngineShaderSource_Linux.cpp, etc. Each one implements RenderingEngine_shaderSourceForName using the appropriate API for that platform.
I use one of two methods. If it's a short shader, I may just put it code:
const char shader[] =
"uniform vec4 blah;\n" // Note, no semicolon here - it does the right thing
"main ()\n"
"{\n"
...rest of code
"}\n";
Or, if it's longer or going to be re-used in other places, I'll put it into a text file in the resources and read the text file at run time. You can get to it via [NSBundle pathForResource:ofType:].
Consider a C++ raw string literal; no STRINGIFY is needed since the newer features of C++ allow you to do similar things without macro.
I'd retype a good example but here is one.