I want to create a pthread with the pthread's function received remotely.
so that the pthread will be compiled separately from the main code and I store it in a known memory location.
when I create the pthread from the main static thread, I only pass the memory location of the pthread's .text without having the pthread's text written in the main code
I'm not experienced with multi-threading. is this idea correct and is there any special instructions or directives that i should use?
Thanks in advance.
This is normally done by linkage.
/* source file 1*/
#include <pthread.h>
extern void *thread(void *); /* better yet, put this in a common header file */
/* ... */
int main(void)
{
int err;
pthread_t thread_id;
/* ... */
err = pthread_create(&thread_id, 0, &thread, 0);
/* ... */
}
/* source file 2 */
void thread(void *)
{
/* ... */
}
You separately compile the files and link together. The linking process ensures that the thread reference in the first file is resolved to the address of the thread function in the other source file.
Related
OBJ-C ONLY...
That is,
An ObjC app imports ObjC static lib A.
Static lib A imports static lib B.
Static lib A has functions that call functions within lib B.
The app only calls functions in lib A and does not call functions in lib B.
Can I assume that lib A or B can be either Obj-C or Swift?
IE. Can an ObjC app import an ObjC-or-Swift static lib A that itself imports a second ObjC-or-Swift static lib B? (yes, 4 use case permutations)
the git repository https://github.com/CombineCppSwiftObjcInStaticLib i created for you is showing this..
your initial #objc func run_central() in BLE_central.swift is exposed, which triggers the precompiler to generate objc compatible headers (bridge) which then again makes it possible to call the function from a method inside .mm(objc++) or .m(objc) when this generated header is imported.
In fact Hub_lib inside the repo is a static ObjC++ lib mixed with Swift. It would work the other way around also. The headers are the key for success here. If you can provide some objc or c or c++ header to swift functions it becomes compatible and wise versa. I mean in general, thats the idea of headers. If you don't have headers, that does not mean you can not call some external stuff, it just means you would call it blind. A proper IDE will complain before you even try to do this evil stuff, unknown entry points aka unknown symbols etc.. So you go for a proper header - always.
To properly combine swift with other languages its good to know there are always two ways of bridging.
In case of Objective-C (and also Objective-C++) it is
Bridging into Swift (projectname-Bridging-Header.h),
and Bridging out of Swift (expose with #objc to trigger automatically internal generation of projectname-Swift.h file. So this header is "invisible" in the file browser on the left side. Nor will you find it in the repo as file, it is named by modulename which is the project-name). The last mentioned header you could even write manually yourself, with lots of troublesome back-draws.
Hint: Executable code is executable code. No matter what language, as far it is compiled for the right device architecture and has symbols to call and you know what to do with the data returned.
Another Hint: there is a way to handle C pointers in swift see docu which become swift datatypes which you can use to go the other way and declare functions to return those from swift.
And direct use of C in Swift is also possible. The compiler considers if you explicit mark some code as C. extern "C" { /* code */ } will cause the C++ compiler to remember, this is still C++ code to compile the function in such a way, it can be called from C (and Swift)
//Example.hpp //no target membership
#ifdef __cplusplus
#include <stdio.h>
class Example {
private:
const char * _name;
public:
Example(const char *name);
~Example(void);
int getLen(void);
};
#endif
There should be an Example.cpp and don't forget to tell Xcode you deal with c++ #ifdef __cplusplus + #endif
//Example.cpp //has target membership
#include "Example.hpp"
#ifdef __cplusplus
#include <stdio.h>
#include <string>
//code implementation according to example.hpp
Example::Example(const char *name) {
_name = name;
}
int Example::getLen() {
return (int)strlen(_name);
}
#endif
//ExampleWrapper.cpp //has target membership
#include "Example.hpp" //c++ header file
extern "C" int myCppFunction(const char *s)
{
// Create an instance of Example, defined in the library
// and call getLen() on it, return result.
return Example(s).getLen();
}
So this function needs to be declared in the bridging header to make use of it.
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
// for extern "C" functions declare them one by one here
// as implemented in ExampleWrapper.cpp
// becomes "func myCppFunction(_ s: UnsafePointer<Int8>!) -> Int32" in swift
int myCppFunction(const char * s);
and then call from swift..
os_log("The result from C++ is %u", myCppFunction("12345"))
So in fact, yes. Integrating a static lib A that calls static lib B in App is possible. Happy compiling as long you offer some header for each part that needs to know what is inside the head of the other lib. That is true for Apps as it is true for libs and frameworks under each other.
Edit here some important stuff to read about Swift Package Manager C support https://github.com/apple/swift-evolution/blob/master/proposals/0038-swiftpm-c-language-targets.md
As long as the libraries export Objective-C compatible symbols, it doesn't matter if they're written in Objective-C, or Swift, or C++, or any other compiled language.
And we know that the Swift compiler exports Objective-C compatible symbols for all declarations that are marked with #objc (either explicitly or implicitly).
From a consumer perspective it doesn't matter which language generated the libraries, as long as the Objective-C compiler/linker can consume the symbols exported by those libraries.
I saw this question: How can I programatically get the list of frameworks and libraries included in an ios project? here, which tries to answer similar question. However, I've two questions on this
The answer in above link (or see code below) - does it provide all frameworks or "only" frameworks that are linked to the project.
for (NSBundle *framework in [NSBundle allFrameworks])
NSLog(#"%#",framework.bundlePath.lastPathComponent);
if I see a framework appearing in above code, how can I find its usage in my code. I see many frameworks being referred to in above code, but I'm not able to figure out where exactly are they used. As per my knowledge, few of them are not used - is there a proper way to find this out.
Update 1:
I made a simple new app with absolutely no code in it. Then, I executed the for loop above and found that, it also presented me with all the frameworks - which means, the code above simply prints all the frameworks and not the one that I am essentially be using in my app. But, does it mean that all frameworks that are printed are linked to the app?
The dynamic loader dyld(3) provides this information. This code will print all loaded frameworks and shared libraries as well:
#include <stdio.h>
#include <dlfcn.h>
#include <mach-o/dyld.h>
int main() {
uint32_t c = _dyld_image_count();
for(uint32_t i = 0; i < c; ++i) {
printf("%d: %s\n", i, _dyld_get_image_name(i));
}
return 0;
}
EDIT: allFrameworks lists only frameworks which are linked to your app, and which contain at least one Objective-C class (see https://developer.apple.com/documentation/foundation/nsbundle/1408056-allframeworks).
Searching for referrers is should be very difficult in general. If you are just looking for a single function, you can add a static implementation of the function and call the loaded variant from it. This technique is used for overwriting __cxa_throw for instance, but it should also work for other functions:
static cxa_throw_t sCxa_throw = 0;
extern "C" void __cxa_throw(void *inException, void *inPvtinfo, void (*inDestination)(void *)) {
if (sCxa_throw == NULL) {
sCxa_throw = (cxa_throw_t)dlsym(RTLD_NEXT, "__cxa_throw");
}
sCxa_throw(inException, inPvtinfo, inDestination);
}
The variable sCXA_throw contains the reference to the dynamic version of this function while the loader uses the static version. Inside of this function you can determine the callers with unwinding the stack with libunwind.
Scene:
I was trying to reverse engineer a mobile substrate dylib. Via IDA, the dylib called MSHookFunction() inside the constructor, and the arguments were from dlopen and dlsym. IDA failed to show the symbols of dlopen and dlsym, so I had to turn to gdb, which could possibly print the 2nd arg of dlsym, a char*, at run time.
Goal:
Break at the very beginning of the constructor of this dylib with gdb.
First Thought:
The constructor of a dylib is executed right after it's loaded, doing all the necessary initializations (Correct me if I'm wrong). So I wrote a command line tool which simply dlopen the dylib and then dlclose it, to run the constructor. FYI, here's the code of the dylib and the command line tool:
// iOSTestDylib.dylib: I'm using [Logos][1] here
%ctor
{
%init;
NSLog(#"snakeninny: ctor of dylib");
}
// iOSTestTool
#include <mach-o/dyld.h>
#include </usr/include/dlfcn.h>
int main(int argc, char **argv, char **envp)
{
NSLog(#"snakeninny: line 6 of command line tool");
void *handle = dlopen("pathOfTheAboveDylib", RTLD_LAZY);
NSLog(#"snakeninny: line 8 of command line tool");
dlclose(handle);
return 0;
}
As you can guess, once I run iOSTestTool, it printed:
snakeninny: line 6 of command line tool
snakeninny: ctor of dylib
snakeninny: line 8 of command line tool
Then setting a break point inside iOSTestDylib.dylib seemed to solve the problem. But I suddenly realized that, before dlopen iOSTestDylib.dylib, the ASLR offset of iOSTestDylib.dylib was unknown, therefore the address of the bp was uncertain. Meanwhile, after dlopen, though we could figure out the ASLR offset, the ctor was already executed, so bp became meaningless. In either situation, I couldn't break inside the constructor of a dylib. Mission failed, and neither did I have a second thought, nor a plan B :(
Question:
What should I do to reach my goal?
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)
{
// ...
}
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.