Related
I am trying to embed Chicken Scheme into a C program, to generate sounds to be played with SDL2's audio system. I would have liked to use the sdl2 egg, but it does not seem to support Audio yet (despite the documentation mentioning the 'audio flag for the init! function).
At first, I was using SDL_QueueAudio from C, passing it a buffer that I had allocated in C and then filled in Scheme. This worked fine, passing a Sint16 * and size_t into Scheme, then using pointer-s16-set! from Scheme to fill it and returning a size_t to note how many cells were filled.
Then, when I realised that using the callback api for generating the audio was much better suited to this, I tried switching to it (having already used it before in C), only for the Scheme function to never be entered. Logging something in the callback function before the Scheme call worked, but logging directly within the Scheme function, or after the Scheme call, never happened.
I can only imagine that this is due to SDL2's audio callback running on a separate thread, and that messing with calling through to Scheme somehow. With this in mind, I tried calling CHICKEN_run(C_toplevel); from within the callback function, the first time that it was called, but that only resulted in a bus error.
So my question is: is there a way of calling embedded Chicken Scheme from SDL2's audio callback?
I am on macOs 10.13.6 High Sierra, with SDL2 and chicken both installed and up-to-date through Homebrew.
I compile with (as I said, this works fine when using the queue audio api):
csc code.c codescm.scm -embedded -o code -L -lSDL2
My simplified code is below:
#include <chicken.h>
#include "SDL2/SDL.h"
extern size_t fill_sound_buffer(Sint16 *buffer, size_t buffer_length);
void fill_sound_callback(void *user_data, Uint8 *stream, int stream_length)
{
// Logging here prints to the console
fill_sound_buffer((Sint16 *)stream, stream_length / 2);
// Logging here does not print to the console
}
void play(void)
{
SDL_AudioSpec audio_want;
SDL_zero(audio_want);
audio_want.freq = 44100;
audio_want.format = AUDIO_S16SYS;
audio_want.channels = 1;
audio_want.samples = 2048;
audio_want.callback = fill_sound_callback;
SDL_AudioSpec audio_have;
SDL_AudioDeviceID audio_device = SDL_OpenAudioDevice(NULL, 0, &audio_want, &audio_have, 0);
SDL_PauseAudioDevice(audio_device, 0);
SDL_Delay(5000);
// Logging here shows up after 5 seconds, but the program then continues to wait
SDL_CloseAudioDevice(audio_device);
}
int main(int argc, char *argv[])
{
SDL_Init(SDL_INIT_AUDIO);
CHICKEN_run(C_toplevel);
play();
SDL_Quit();
return 0;
}
(import (chicken format)
(chicken foreign)
(chicken memory)
(chicken platform))
(define-external (fill_sound_buffer ((c-pointer short) buffer) (size_t buffer_length)) size_t
; This never prints when using the callback api
(printf "In Scheme~%")
; Removed the code that calculates a sine wave and fills the buffer with it, which works
0)
(return-to-host)
I want to use a dll-file in my C-Code, but are very confused about the syntax.
My Story: I made a simple function in Matlab ( f(x1,x2)=x1*x2 ), with the "Matlab Coder" I translated it to C-Code and generated an exe, I could run it from the terminal with arguments.Now I generated a dll instead of an exe and want to use the dll.
Since now I could not make Code explanations, I googled, make work for me. I look up Syntax in http://en.cppreference.com/w/ but for my surprise there wasn't even an entry for e.g. GetProcAddress or LoadLirbary.
Here is the C-Code in which I would like to use the dll:
#include <stdio.h>
#include <stdlib.h>
/*
* In my dream I would load the dll function here
* with something like Load(mytimes4.dll)
*/
int main(int argc, char *argv[]) {
double x1,x2,myresult;
//Load Arguments from Terminal
sscanf(argv[1], "%lf", &x1);
sscanf(argv[2], "%lf", &x2);
// Use and print the function from mytimes4.dll
myresult = mytimes4(x1,x2);
printf("%3.2f\n",myresult);
return 0;
}
After generating the dll, Matlab gave me the following folder:
"dll-folder" produced by Matlab
Can someone give me a most simple but complete Code that would work with my example? What files are needed (maybe .def or .exp)? Also for Explanations of the lines involved using the dll I would be gratefull. Or if not, you maybe have some background knowledge that makes the complex syntax reasonable.Thanks in advance!
System information: Windows 7 Pro 64, Matlab 64 2016b, gcc cygwin 64, eclipse ide.
With the link of thurizas I could solve my problem.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686944(v=vs.85).aspx
I copied the code from the side. Below you can see the code with additional comments of mine and with ,in my opinion, more clearly naming. Thus it is probably easier to use for beginners as I am.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
/*Declaration of the function,contained in dll, as pointer with the arbitrary pointer name
"*MYFUNCTIONPOINTER" (not sure if it has to be in big letters).
In my case the function means simply f(x1,x2) = x1*x2 and is thus as double declared*/
typedef double (*MYFUNCTIONPOINTER)(double, double);
int main() {
HINSTANCE hinstLib;
//"myfunction" is the arbitrary name the function will be called later
MYFUNCTIONPOINTER myfunction;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
//Tell the dll file
hinstLib = LoadLibrary(TEXT("mypersonal.dll"));
if (hinstLib != NULL)
{
/* At this line "myfunction" gets its definition from "MYFUNCTIONPOINTER"
and can be used as any other function.The relevant function in the dll has
to be told here.*/
myfunction = (MYFUNCTIONPOINTER) GetProcAddress(hinstLib, "mydllfunction");
// If the function address is valid, call the function.
if (NULL != myfunction)
{
fRunTimeLinkSuccess = TRUE;
// The function can be used.
double myoutput;
myoutput = myfunction(5,7);
printf("%f\n",myoutput);
getchar();
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
return 0;
}
I'm trying to write a demo PAM module in C, which uses Embedding Python in C concept to run a script written in python (2.7), inside pam_sm_authenticate() function, which is written in C file (pam_auth.c).
This is the python script: test.py
import math
import numpy
def test_func():
a = "test"
return a
The path for test.py is /usr/lib/Python2.7/ so that I can easily import it.
This is the C file:
#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
#define PAM_SM_SESSION
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <security/pam_appl.h>
#include<python2.7/Python.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define NOBODY "nobody"
/*PAM Stuffs*/
PAM_EXTERN int pam_sm_authenticate(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
const char *user;
int retval;
user = NULL;
retval = pam_get_user(pamh, &user, NULL);
if(retval != PAM_SUCCESS)
{
fprintf(stderr, "%s", pam_strerror(pamh, retval));
// return (retval);
}
fprintf(stdout, "retval= %d user=%s\n", retval,user);
if (user == NULL || *user =='\0')
pam_set_item(pamh, PAM_USER, (const char*)NOBODY);
/* Python Wrapper */
// Set PYTHONPATH TO working directory
//int res = setenv("PYTHONPATH",".",1);
//fprintf(stdout, "%d", res);
PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pResult;
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyString_FromString((char*)"test");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
PyErr_Print();
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"test_func");
if (PyCallable_Check(pFunc))
{
pValue=NULL;
PyErr_Print();
pResult=PyObject_CallObject(pFunc,pValue);
PyErr_Print();
}else
{
PyErr_Print();
}
printf("Result is %s\n",PyString_AsString(pResult));
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);/* */
// Finish the Python Interpreter
Py_Finalize();
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_setcred(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_acct_mgmt(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_open_session(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_close_session(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_chauthtok(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}
The C-file is just a modification of pam_permit.c. The C file is compiled using gcc ( gcc -shared -o pam_auth.so -fPIC pam_auth.c -I/usr/include/python2.7 -lpython2.7 ) to obtain an .so file (pam_auth.so) and is put inside the folder /lib/security/
I changed the PAM configuration of 'sudo' file in /etc/pam.d as follows:
#%PAM-1.0
auth required pam_env.so readenv=1 user_readenv=0
auth required pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0
##include common-auth #this line is commented to make it use my pam module
auth required pam_auth.so
#include common-account
#include common-session-noninteractive
The line "auth required pam_auth.so" forces the system to use my module for authentication everytime I use the command "sudo". (for ex- sudo nautilus)
Now the problem is:
This line in C file " pModule = PyImport_Import(pName); " gives an import error, which is printed by PyErr_Print() as follows:
stitches#Andromida:~$ sudo nautilus
retval= 0 user=stitches
Traceback (most recent call last):
File "/usr/lib/python2.7/subho_auth.py", line 8, in <module>
import numpy
File "/usr/lib/python2.7/dist-packages/numpy/__init__.py", line 153, in <module>
from . import add_newdocs
File "/usr/lib/python2.7/dist-packages/numpy/add_newdocs.py", line 13, in <module>
from numpy.lib import add_newdoc
File "/usr/lib/python2.7/dist-packages/numpy/lib/__init__.py", line 8, in <module>
from .type_check import *
File "/usr/lib/python2.7/dist-packages/numpy/lib/type_check.py", line 11, in <module>
import numpy.core.numeric as _nx
File "/usr/lib/python2.7/dist-packages/numpy/core/__init__.py", line 6, in <module>
from . import multiarray
ImportError: /usr/lib/python2.7/dist-packages/numpy/core/multiarray.so: undefined symbol: PyExc_SystemError
Segmentation fault (core dumped)
As per I can understand,it fails to import numpy library as specified in test.py file. How to solve this problem of ImportError & PyExc_SystemError?
The python script works as charm if I run in as follows:
#include <Python.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// Set PYTHONPATH TO working directory
//int res = setenv("PYTHONPATH",".",1);
//fprintf(stdout, "%d", res);
PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pResult;
// Initialize the Python Interpreter
Py_Initialize();
// Build the name object
pName = PyString_FromString((char*)"test");
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
PyErr_Print();
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"test_func");
if (PyCallable_Check(pFunc))
{
pValue=NULL;
PyErr_Print();
pResult=PyObject_CallObject(pFunc,pValue);
PyErr_Print();
}else
{
PyErr_Print();
}
printf("Result is %s\n",PyString_AsString(pResult));
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);/* */
// Finish the Python Interpreter
Py_Finalize();
return 0;
}
If it works under general python embedding examples, why its not working in PAM-based embedding examples (where .so files are used)?
PS: I'm importing numpy for a particular reason. Don't ask why I've not used in anywhere in python script as this is just a demo script of what I'm trying to achieve. Moreover, import math doesn't give any import error. I get import error for SciPY too.
PPS: Numpy and Scipy packages works perfect in python scripts and is installed under /usr/lib/python2.7/dist-packages/. I'm using ubuntu 14.04.
Please help!!!!
I don't know the answer to your question, but I am wondering why it didn't fail earlier. The host application does not know your PAM module will be needed using libpython2.7.so.1, so somehow that must being loaded dynamically otherwise the Py_Initialize() call would fail with the same error.
Given you say it doesn't fail there it must be loaded. However from the error you are getting we can deduce the symbols it contains (such as PyExc_SystemError) are not visible to dynamic libraries subsequently loaded. This is the default when libraries are loaded using dlopen() (see RTLD_LOCAL in man 3 dlopen). To override it, you must pass RTLD_GLOBAL to dlopen(). Maybe that's your problem.
Other comments about your code:
Calling Py_Initialise() for each pm_sm_...() call is going to be expensive and possibly surprising to the python modules. It means all data the python module accumulated within one call (like say voice or the user name) will be discarded when the next call is made. You are better off loading libpython2.7.so.1 and initialising PAM once, then using the cleanup function of pam_set_data() to unload it when you are done.
In a related issue, your PAM module isn't usable from Python programs because you always call Py_Initialise() (and I presume the matching call to Py_Finalize()).
If you program hadn't fallen over where it did, it would have fallen over on the line printf("Result is %s\n",PyString_AsString(pResult)) because pResult isn't initialised.
As I think you know, all the boilerplate you have here to let you wring PAM modules in Python is provided by pam-python - no C required. Since you are evidently writing your PAM module in Python anyway, you are already exposed to the overheads it incurs but are missing out on the features it provides like logging uncaught Python exceptions. And most importantly, using it means you can avoid C entirely. Your PAM module will be loaded into programs that guard the security of the machine - programs like login, sudo, and xdm/gdm3. Avoiding C means also avoiding the legions of security bugs C programs can have that are impossible in Python - buffer overruns, uninitialised pointers and accessing free'ed memory. Since you have one of those bugs in your the C code you posted here, avoiding it sounds like a good idea.
A while ago I wrote a script in C that used the Windows API functions EnumWindows, SetWindowPos and SetForegroundWindow to automatically arrange windows (by title) in a particular layout that I commonly wanted.
Are there Linux equivalents for these functions? I will be using Kubuntu, so KDE-specific and/or Ubuntu-specific solutions are fine.
The best way to do this is either in the window manager itself (if yours supports extensions) or with the protocols and hints designed to support "pagers" (pager = any non-window-manager process that does window organization or navigation things).
The EWMH spec includes a _NET_MOVERESIZE_WINDOW designed for use by pagers. http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#id2731465
Raw Xlib or Xcb is pretty rough but there's a library called libwnck specifically designed to do the kind of thing you're talking about. (I wrote the original library long ago but it's been maintained by others forever.) Even if you don't use it, read the code to see how to do stuff. KDE may have an equivalent with KDE-style APIs I'm not sure.
There should be no need to use anything KDE or GNOME or distribution specific since the needed stuff is all spelled out in EWMH. That said, for certain window managers doing this as an extension may be easier than writing a separate app.
Using old school X calls directly can certainly be made to work but there are lots of details to handle there that require significant expertise if you want to iron out all the bugs and corner cases, in my opinion, so using a WM extension API or pager library would be my advice.
#andrewdotn has a fine answer there but you can do this old school as well fairly simply by walking the tree starting at the root window of the display using XQueryTree and fetching the window name with XFetchName then moving it with XMoveWindow. Here is an example that will list all the windows and if any are called 'xeyes' they get moved to the top left. Like most X programs, there is more to it and this should probably be calling XGetWindowProperty to fetch the _NET_WM_NAME extended window manager property but the example works ok as a starter. Compile with gcc -Wall -g -o demo demo.c -lX11
#include <X11/Xlib.h>
#include <stdio.h>
#include <string.h>
static int
EnumWindows(Display *display, Window window, int depth)
{
Window parent, *children;
unsigned int count = 0;
int r = 1, n = 0;
char *name = NULL;
XFetchName(display, window, &name);
for (n = 0; n < depth; ++n) putchar(' ');
printf("%08x %s\n", (int)window, name?name:"(null)");
if (name && strcmp("xeyes", name) == 0) {
XMoveWindow(display, window, 5, 5);
}
if (name) XFree(name);
if (XQueryTree(display, window, &window, &parent, &children, &count) == 0) {
fprintf(stderr, "error: XQueryTree error\n");
return 0;
}
for (n = 0; r && n < count; ++n) {
r = EnumWindows(display, children[n], depth+1);
}
XFree(children);
return r;
}
int
main(int argc, char *const argv[])
{
Display *display = NULL;
if ((display = XOpenDisplay(NULL)) == NULL) {
fprintf(stderr, "error: cannot connect to X server\n");
return 1;
}
EnumWindows(display, DefaultRootWindow(display), 0);
XCloseDisplay(display);
return 0;
}
Yes, you can do this using the X Windows protocol. It’s a very low-level protocol so it will take some work. You can use xcb_query_tree to find the window to operate on, and then move it with xcb_configure_window. This page gives some details on how to do it. There’s a basic tutorial on using the library those functions come from, but you’ll probably want to Google for a better one.
It may seem daunting, but it’s not too bad. Here’s a 50-line C program that will move all your xterms 10px to the right:
#include <stdio.h>
#include <string.h>
#include <xcb/xcb.h>
void handle(xcb_connection_t* connection, xcb_window_t window) {
xcb_query_tree_reply_t *tree = xcb_query_tree_reply(connection,
xcb_query_tree(connection, window), NULL);
xcb_window_t *children = xcb_query_tree_children(tree);
for (int i = 0; i < xcb_query_tree_children_length(tree); i++) {
xcb_get_property_reply_t *class_reply = xcb_get_property_reply(
connection,
xcb_get_property(connection, 0, children[i], XCB_ATOM_WM_CLASS,
XCB_ATOM_STRING, 0, 512), NULL);
char* class = (char*)xcb_get_property_value(class_reply);
class[xcb_get_property_value_length(class_reply)] = '\0';
if (!strcmp(class, "xterm")) {
/* Get geometry relative to parent window */
xcb_get_geometry_reply_t* geom = xcb_get_geometry_reply(
connection,
xcb_get_geometry(connection, window),
NULL);
/* Move 10 pixels right */
uint32_t values[] = {geom->x + 10};
xcb_configure_window(connection, children[i],
XCB_CONFIG_WINDOW_X, values);
}
/* Recurse down window tree */
handle(connection, children[i]);
}
}
int main() {
xcb_connection_t *connection;
const xcb_setup_t *setup;
connection = xcb_connect(NULL, NULL);
setup = xcb_get_setup(connection);
xcb_screen_iterator_t screen = xcb_setup_roots_iterator(setup);
handle(connection, screen.data->root);
return 0;
}
There’s no error-checking or memory management, and what it can do is pretty limited. But it should be straightforward to update into a program that does what you want, or to turn it into a general-purpose helper program by adding command-line options to specify which windows to operate on and which operations to perform on them.
As it seems you are not looking specifically for a solution in code, but rather in a desktop environment, you need to take a look at one of the window managers that handle the window placement in such a desktop environment.
KDE's KWin's Window Attributes
Compiz (GNOME) has "Window Rules" and "Place Windows" in the CompizConfig Settings Manager application. See e.g. here
Openbox seems a lot harder to get right, although they link to a GUI tool at the bottom of this page.
The problem with using X directly is that X in itself knows nothing about your desktop environment (panels, shortcuts, etc.) and you'll have to compensate manually.
After googling for this, I'm surprised KDE is the only one that has a simple way to do this.
I'm coding some similar programs in C as part of an XCode project. As this new program needs to exhibit some slightly different functionality to what the 1st working iteration was, I thought targets were the best thing to use.
So I tried to create a new target, and did it the way I thought was the right way from googling how to (in XCode). But on compilation, I get way too many errors.
Here is a screen of the errors I get:
I see that it's having a problem with loads of different characters, so I'm sure it's probably a simple problem like some missing files. But I didn't know what to Google so I hope it's okay that I'm asking.
On a related note, does anyone know why my first version of the program, called main.c, didn't need to include a header file like the one above did?
Thanks!
EDIT:
Here's the code from the new target, which is practically identical to the so far unchanged first version of the program:
/*
* ScalarProduct.c
* Concurrency_Practical1
*
* Created by Chucky on 11/03/2012.
* Copyright 2012 __MyCompanyName__. All rights reserved.
*
*/
#include "ScalarProduct.h"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
//the final answer
int finalScalarProd;
//random variable
int rand_seed=10;
int rand()
{
int n;
n = random()%11;
//printf("%d\n", n);
return(n);
}
void* getScalarProduct(void *arg)
{
//index for loop
int i;
//scalarProduct of 10 integers
int * scalarProd = (int *) arg;
//my two arrays
int list1[10];
int list2[10];
for (i=0; i<10; i++) {
list1[i] = rand();
list2[i] = rand();
*scalarProd += list1[i]*list2[i];
printf("%d:\t\t %d\t\t %d\t\t %d\t\t\n", i, list1[i], list2[i], list1[i]*list2[i]);
}
return((void*)scalarProd);
}
int main (int argc, const char * argv[]) {
// insert code here...
pthread_t t1, t2;
int sp1= 0, sp2 = 0;
printf("Index\t List1\t List2\t Product\n\n");
pthread_create( &t1, NULL, getScalarProduct, &sp1);
pthread_create( &t2, NULL, getScalarProduct, &sp2);
pthread_join( t1, NULL);
pthread_join( t2, NULL);
printf("\nScalar Products: %d %d\n", sp1, sp2);
finalScalarProd = sp1 + sp2;
printf("Result: %d\n", finalScalarProd);
return 0;
}
From the errors, it almost looks as if you are mixing Objective-C headers and compiling with the C compiler. It's still hard to tell though.
Your project is including/importing the AppKit-Header, which is ObjectiveC and not pure C.
As your quoted source does not mention it, I would bet that it is imported within the precompiled header. Check your project's precompiled header for such entry/ies. It will be named just like your project, with the extension .pch. You may want to remove any ObjectiveC imports.
Also check if you used any ObjectiveC frameworks in your project. When in doubt, remove all listed frameworks from your project.