We know that we call pthread like this:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void* arg);
Hi guys, i want to know why the return type of third parameter is void*? why not void?
Because there is no way for a start function to know what kind of data a developer wants to return from the function they use a void* that can point to any type. It is up to the developer of the start function to then cast the void* to appropriate type he actually returned before using whatever the void* points to. So now the start function can return a pointer that may in actually point to anything. If the start function is declared to return void, it means this function returns nothing, then what if the developer wants the start function to return a int, a struct? For example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
struct test {
char str[32];
int x;
};
void *func(void*) {
struct test *eg = (struct test *)malloc(sizeof(struct test));
strcpy(eg->str,"hello world");
eg->x = 42;
pthread_exit(eg);
}
int main (void) {
pthread_t id;
struct test *resp;
pthread_create(&id, NULL, func, NULL);
pthread_join(id,(void**)&resp);
printf("%s %d\n",resp->str,resp->x);
free(resp);
return 0;
}
More details on this post: What does void* mean and how to use it?
Related
You can write the prototypes without the variable names?
int example(examplestruct *var1, examplestruct *var2);
void done(examplestruct *var1,FILE *f);
struct {
int* field1;
int field2;
}examplestruct;
Is it possible to write the prototypes without name variables?
Can anyone tell me if this is acceptable in C language? You can write the prototypes without the variable names?
Yes.
As for the second question:
If you want a function to be inside main(), then take the body of the function, put it in main() and make sure that the arguments that the function had are well handled.
This example will clear things up:
#include <stdio.h>
void print(int);
void inc_p(int);
int main(void) {
int num = 5;
print(num);
inc_p(num);
// to get rid of inc_p(), copy paste it's body inside main
// and you will get this
// a++;
// print(a);
// However, a was an argument, here you need to use
// the variable declared in main(), i.e. 'num'
num++;
print(num);
return 0;
}
void print(int a) {
printf("%d\n", a);
}
void inc_p(int a) {
a++;
print(a);
}
I want to find out type informations of every functions using by Clang libtool.
However, VisitReturnStmt sometimes cannot find any return statements.
Also, class type return(eg. ASTConsumer * in "CreateASTConsumer" method) is converted to "int *" type.
(another case: bool -> _Bool)
How can I find out real return types for every functions?
Thanks in advance for your help.
The tool source and the input cpp source are same as follows.
#include "clang/Driver/Options.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace llvm;
Rewriter TheRewriter;
class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
private:
ASTContext *astContext; // used for getting additional AST info
public:
explicit ExampleVisitor(CompilerInstance *CI)
: astContext(&(CI->getASTContext())) // initialize private members
{
TheRewriter.setSourceMgr(astContext->getSourceManager(), astContext->getLangOpts());
}
virtual bool VisitReturnStmt(ReturnStmt *ReturnStatement) {
ReturnStatement->getRetValue()->dump(TheRewriter.getSourceMgr());
return true;
}
virtual bool VisitStmt(Stmt *S) {
S->dump(TheRewriter.getSourceMgr());
return true;
}
};
class ExampleASTConsumer : public ASTConsumer {
private:
ExampleVisitor *visitor; // doesn't have to be private
public:
// override the constructor in order to pass CI
explicit ExampleASTConsumer(CompilerInstance *CI)
: visitor(new ExampleVisitor(CI)) // initialize the visitor
{ }
// override this to call our ExampleVisitor on the entire source file
virtual void HandleTranslationUnit(ASTContext &Context) {
/* we can use ASTContext to get the TranslationUnitDecl, which is
a single Decl that collectively represents the entire source file */
visitor->TraverseDecl(Context.getTranslationUnitDecl());
}
};
class ExampleFrontendAction : public ASTFrontendAction {
public:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef file) {
return new ExampleASTConsumer(&CI); // pass CI pointer to ASTConsumer
}
};
int main(int argc, const char **argv) {
// parse the command-line args passed to your code
CommonOptionsParser op(argc, argv);
// create a new Clang Tool instance (a LibTooling environment)
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
// run the Clang Tool, creating a new FrontendAction (explained below)
int result = Tool.run(newFrontendActionFactory<ExampleFrontendAction>());
return result;
}
If I'm interpreting the clang docs correctly
Note that GCC allows return with no argument in a function declared to return a value, and it allows returning a value in functions declared to return void. We explicitly model this in the AST, which means you can't depend on the return type of the function and the presence of an argument.
this implies that you can't reliably infer the return type of a function from its return statement.
If you want to find the return type of a function, you could visit FunctionDecl nodes and call FunctionDecl::getReturnType() on them
We know that we call pthread like this
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void* arg);
However, if in the start_routine function I wanna call has more than one argument, what can I do?
You can put whatever you want into a struct and pass a pointer to that.
In C:
typedef struct {
int a;
int b;
} ChildMainArgs;
void child_main(int a,int b);
void child_main_thread(void *arg)
{
ChildMainArgs *args_ptr = (ChildMainArgs *)arg;
child_main(args_ptr->a,args_ptr->b);
}
ChildMainArgs args;
args.a = 5;
args.b = 7;
pthread_create(..,..,child_main_thread,&args);
Usually one would only push 'userdata' when the data isn't any of Lua's standard types (number, string, bool, etc).
But how would you push an actually Function pointer to Lua (not as userdata; since userdata is not executable as function in Lua), assuming the function looks like so:
void nothing(const char* stuff)
{
do_magic_things_with(stuff);
}
The returned value should behave like the returned value from this native Lua function:
function things()
return function(stuff)
do_magic_things_with(stuff)
end
end
Is this possible to do with the C API? If yes, how (Examples would be appreciated)?
EDIT: To add some clarity, The value is supposed to be returned by a function exposed to Lua through the C API.
Use lua_pushcfunction
Examples are included in PiL
Here is an example that follows the form of the currently accepted answer.
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <stdio.h>
/* this is the C function you want to return */
static void
cfunction(const char *s)
{
puts(s);
}
/* this is the proxy function that acts like cfunction */
static int
proxy(lua_State *L)
{
cfunction(luaL_checkstring(L, 1));
return 0;
}
/* this global function returns "cfunction" to Lua. */
static int
getproxy(lua_State *L)
{
lua_pushcfunction(L, &proxy);
return 1;
}
int
main(int argc, char **argv)
{
lua_State *L;
L = luaL_newstate();
/* set the global function that returns the proxy */
lua_pushcfunction(L, getproxy);
lua_setglobal(L, "getproxy");
/* see if it works */
luaL_dostring(L, "p = getproxy() p('Hello, world!')");
lua_close(L);
return 0;
}
You could return a userdata with a metatable that proxies your C function through the __call metamethod. That way the userdata could be called like a function. Below is a full program example.
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <stdio.h>
/* this is the C function you want to return */
static void
cfunction(const char *s)
{
puts(s);
}
/* this is the proxy function that will be used as the __call metamethod */
static int
proxy(lua_State *L)
{
luaL_checkudata(L, 1, "proxy");
cfunction(luaL_checkstring(L, 2));
return 0;
}
/* this global function returns the C function with a userdata proxy */
static int
getproxy(lua_State *L)
{
lua_newuserdata(L, sizeof (int));
luaL_getmetatable(L, "proxy");
lua_setmetatable(L, -2);
return 1;
}
int
main(int argc, char **argv)
{
lua_State *L;
L = luaL_newstate();
/* create the proxy metatable */
luaL_newmetatable(L, "proxy");
lua_pushcfunction(L, proxy);
lua_setfield(L, -2, "__call");
/* set the global function that returns the proxy */
lua_pushcfunction(L, getproxy);
lua_setglobal(L, "getproxy");
/* see if it works */
luaL_dostring(L, "p = getproxy() p('Hello, world!')");
lua_close(L);
return 0;
}
In retrospect, I completely over-thought what you are asking. All you really need to do is to create a function of type lua_CFunction that pulls the parameters from the Lua stack and passes them on to the target C function. The code above answers your question literally, but it is probably overkill for what you really need to accomplish.
For a user-lever thread library, I need to figure out jumping to a function by modifying PC value stored in jmp_buf.
This is what I have written:
jmp_buf env;
void print (void) {
printf("\nHello World!");
}
static int ptr_mangle(int p) {
unsigned int ret;
asm(" movl %1, %%eax;\n"
" xorl %%gs:0x18, %%eax;"
" roll $0x9, %%eax;"
" movl %%eax, %0;"
: "=r"(ret)
: "r"(p)
: "%eax"
);
return ret;
}
int main() {
int i = setjmp(env);
env[0].__jmpbuf[5] = ptr_mangle(print);
longjmp(env, 2);
return 0;
}
I am trying to modify PC in jmp_buf by setting it to the address of the function I am trying to jump to.
I am getting a segmentation fault.
I am unable to figure out what exactly needs to be done. Do I need to modify SP as well?
Any help would be very much appreciated.
What are you trying to do? Are you not checking for the return value of setjmp? I don't think you are doing this correctly. Have a look at the sample code below to see what would be the output be:
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
void subroutine(jmp_buf);
int main(void)
{
int value;
jmp_buf jumper;
value = setjmp(jumper);
if (value != 0)
{
printf("Longjmp with value %d\n", value);
exit(value);
}
printf("About to call subroutine ... \n");
subroutine(jumper);
return 0;
}
void subroutine(jmp_buf jumper)
{
longjmp(jumper,1);
}
The output would be:
About to call subroutine...
Longjmp with a value of 1.
Which begs the question - why are you trying to modify the IP? It sounds like you overwrote something or the code 'jumped' off into the woods and trampled something and came back with a hard landing i.e. segfault.
The variable env is specifically a struct, do not use an array subscript as you have done. I suspect that is why you got a segfault...
Hope this helps,
Best regards,
Tom.