I have a compiled a library and I am trying to access the functions from c++ code. Most functions work properly, however I have some trouble with passing parameters to a function that accepts an array as argument.
The pascal function header is defined as:
function MyFunc( const Name : PAnsichar;
const MyArr : array of single;
const ArrLength : Longint;
var output : single
): Longint;
I can compile this function and use is properly when using pascal to load the function and call the functions in the library. Note: the library is compiled using the CDecl calling convention.
However I have trouble with loading the functions in C++.
The function is defined as:
typedef long (*MyFunc)(char *, float, long, float *);
I am able to load the dll properly and acces all the function properly, all but the one above.
long ArrLeng = 300;
float out;
float Arr[ArrLeng];
\\ fill the array
result = MyFunc((char *) "default", Arr[0], ArrLeng, &out);
I can attach the debugger to the library and check the variables read by the library. The strange thing is that the Name and ArrLeng variables are passed on properly, but the array is not passed properly.
What am I doing wrong? How should I pass the array to the library?
Try passing a pointer to the first element. "Array of Single" is a so called open array which is a pascal construct that also passes array boundary information.
However when used in combination with cdecl afaik it reduces to a pointer to elementtype. (single *) At least Free Pascal does, I don't know what Delphi/Kylix does.
In doubt let pascal call it and check the resulting assembler.
Related
I'm using VxWorks 6.9 and am trying to use some spyLib.h functions but I'm having issues finding what signature to expect given that the type is variadic.
in vxTypesOld.h I find my type: typedef int (*FUNCPTR) (...);
and in spyLib.h i have my function call : extern void spyReportCommon (FUNCPTR printRtn);
But what function parameters are expected for printRtn ? I guess a c-style string is one but I don't know if each line of the table is a string or if its an array of strings, or even one large string.
I can't start writing the function to parse data from the outputted data until I know in what form that data is passed into the function.
All I know for certain is that it returns an int (e.g. int parsePrint( ???? );)
Here is my attempt at reporting:
#include <vxworks.h>
#include <spyLib.h>
#include <usrLib.h>
int ParseSpy(const char * spyOutput); // this is a guess
void Startup()
{
//startup logic
// the compiler said and int param is expected but the .h had void
spyLibInit(1);
spyCommon(1,50, (FUNCPTR) &ParseSpy);
}
int ParseSpy(const char * spyOutput){} // this is a guess
I'm getting an unexpected compiler error: 'spyCommon' was not declared in scope
but as you can see spyLib.h was included so I'm a bit confused by this.
That looks like a bad design. The print function cannot print if it does not know what the parameters are. At least one parameter is needed to specify what the rest of the parameters are.
Looking at the source and searching for "printRtn" I see that all calls to the print function are expecting a printf like function where the first parameter is a format string. Your function should better be written as
int ParseSpy(const char * spyOutput, ...);
Regarding the missing spyCommon you could try to let VxWorks write the preprocessor output to a file to check what the compiler sees. Maybe you are getting the wrong spylib.h file or something it that file is hidden by #if.
So I am trying to send the names of functions called through call instructions I find in a program to an external function as a string. So the declaration of my external function is: void func(string s); In my LLVM pass I am trying to pass a value to the parameter s. I am stuck at adding the function declaration of func using getOrInsertFunction, here is a code snippet:
Function * func;
Constant * funcDec = M.getOrInsertFunction("func",
Type::getVoidTy(M.getContext)), ???);
I am confused about what to put in place of ???.
As an example Type::getInt32Ty(M.getContext()) is used if the parameter is int. I know LLVM doesn't have std::string. So how can I achieve passing a string to an external function?
Thanks!
String is basically character pointer. Char is 8 bit. So you can put
Type::getInt8PtrTy(M.getContext()) in place of ???.
I'm debugging a x86 program (written in C++ / VS2012 / statically linked) in WinDbg and I have its object files. My point of interest is this function:
static bool isValidToken(const std::string& token)
This function receives a string token to validate a client.
I want to be able to test it inside the debugger, but to do so I would have to create an std::string so I could do the command: .call isValidToken(<addr_of_string>).
Dumping and manipulating std::string inside WinDbg is relatively easy, but is it possible to create it?
I'm able to hijack other strings and change it so I can test, but it obviously crashes the program sometimes. I'm trying to find a static constructor for the class but it's really hard because it's heavily based on templates.
By debugging a test program in Visual Studio (suggested by #cdonts in the comments) I could find the constructor prototype for std::string. It is shown in the command that follows.
Back to WinDbg I issued the following command to find symbols with that signature (note that * is used as wildcard to replace spaces):
0:047> x Manager!std::basic_string<char,std::char_traits<char>,std::allocator<char>*>::basic_string<char,std::char_traits<char>,std::allocator<char>*>
Found the following constructors:
6e36bf96 Manager!std::basic_string<...PROTOTYPE...> (char *, char *)
6e67fa65 Manager!std::basic_string<...PROTOTYPE...> (class std::basic_string<...PROTOTYPE...> *, int, int)
6d519218 Manager!std::basic_string<...PROTOTYPE...> (class std::_String_const_iterator<...PROTOTYPE...>)
6d54c745 Manager!std::basic_string<...PROTOTYPE...> (char *, unsigned int)
6d0c2666 Manager!std::basic_string<...PROTOTYPE...> (char *)
6d1f2a43 Manager!std::basic_string<...PROTOTYPE...> (class std::basic_string<...PROTOTYPE...> *)
6d151eb8 Manager!std::basic_string<...PROTOTYPE...> (class std::basic_string<...PROTOTYPE...> *)
I ommited some parts of the prototypes, but the one that interests us is:
6d0c2666 Manager!std::basic_string<...PROTOTYPE...> (char *)
This one only takes a char * as argument. It is used to initialize the newly created string, and it's really easy to provide. So, the steps to do the job are:
Allocate memory for the object ( std::string ). We use 1000 because it's the minimum allocation size:
0:047> .dvalloc 1000
Allocated 1000 bytes starting at 03fe0000
Allocate a buffer for the char * parameter:
0:047> .dvalloc 1000
Allocated 1000 bytes starting at 03ff0000
We can initialize the buffer with:
0:047> ea 0x03ff0000 "my string here"
Place a .call command passing two parameters: The first one is the address of the memory we allocated for the object itself, that actually happens to be a this argument, because the funcion uses thiscall calling convention (WinDbg knows it and places it in ecx). The second one is the char * parameter for the constructor:
0:048> .call 6d0c2666(0x03fe0000, 0x03ff0000)
Thread is set up for call, 'g' will execute.
WARNING: This can have serious side-effects,
including deadlocks and corruption of the debuggee.
0:048> g
After that we have a good std::string object (at 0x03fe0000) to work with, containing the text "my string here".
I have to classes, an Executer with these methods:
Executer()
struct Execute(string s)
Lookup(string name, int module, int num, ...)
and a Parser:
Parser()
struct Parse(string s)
The Exectuers Execute method calls the Parsers Parse method. The Parser then chucks the string into smaller bits (it explodes the string on the ;-sign) and returns a struct to the Execute method. This struct it uses to call the Lookup method.
The struct that the Parse returns holds some standard information:
An command name
A senderId (a username, a mac address and a password)
A variable number of arguments
And that is my problem. The Lookup method take variable arguments, but how do I handle the the hand over of these variable arguments by the struct? Im not an expert in C and C++. Should I mass the two classes togheter? So the Parser method could call the Execute method, sparing the struct away.
Or maybe there is a way of parsing an unknown variable of arguments at runtime? By some sort of array?
EDIT
I cant use the STL library from C++. I only use the C++ class and virtual feature. Im writing to an compiler where Im restricted to use almost all of the C libraries + the magic skills of C++ (virtual and class). SOory for not telling that right away.
EDIT 2
Im writing code to an embedded system and thereby using avr-gcc to compile my code. Thats why I cant use STL. The avr-gcc doesnt support this.
Use std::vector<> or a simular container that can hold an arbitrary number of entries.
struct {
std::string commandName;
sender_t senderId;
std::vector<arg_t> arguments;
};
Edit: oh, you can't use std::vector. In that case: use an array and store the length:
struct {
const char* commandName;
sender_t senderId;
int argumentCount;
int maxArgumentCount; // you might not need this
arg_t* arguments; // pointer to array of (at least) argumentCount elements.
};
Use malloc() or new() to create the array for the arguments.
I would suggest to wrap the argumentCount, maxArgumentCount and arguments in a separate class, which can handle the malloc/new and free/delete as well. This will make it easier to prevent memory leaks.
In the end, you'll have written your own vector_of_arg_t class, so maybe have a look at some basic vector implementation. There must be tutorials on that on the web.
You could declare your Lookup method as follows:
void Lookup(string name, int module, int num, std::vector<std::string> &args);
By storing the variable arguments in an args array, you can have as many as you want.
See
Q: How can I write a function which takes a variable number of arguments and passes them to some other function (which takes a variable number of arguments)?
A: In general, you cannot. Ideally, you should provide a version of that other function which accepts a va_list pointer.
Suppose you want to write a faterror function which will print a fatal error message, then exit. You might like to write it in terms of the error function of question 15.5:
void faterror(const char *fmt, ...)
{
error(fmt, what goes here? );
exit(EXIT_FAILURE);
}
but it's not obvious how to hand faterror's arguments off to error.
<snip>
Read on at
http://c-faq.com/varargs/handoff.html
There's a function, written in C++ and compiled as DLL, which I want to use in my Delphi application.
Scraper.cpp:
SCRAPER_API bool ScraperGetWinList(SWin winList[100])
{
iCurrWin=0;
memset(winList,0,100 * sizeof(SWin));
return EnumWindows(EnumProcTopLevelWindowList, (LPARAM) winList);
}
Scraper.h:
#ifdef SCRAPER_EXPORTS
#define SCRAPER_API __declspec(dllexport)
#else
#define SCRAPER_API __declspec(dllimport)
#endif
struct SWin
{
char title[512];
HWND hwnd;
};
extern "C" {
SCRAPER_API bool ScraperGetWinList(SWin winList[100]);
}
This is how I declare the function in the Delphi application:
type
tWin = record
Title: Array [0..511] of Char;
hWnd: HWND;
end;
tWinList = Array [0..99] of tWin;
function ScraperGetWinList(var WinList: tWinList): Boolean; stdcall; external 'Scraper.dll';
The function works, but when it's finished, I receive Debugger Fault Notification: Project ... faulted with message: ''access violation at 0x0012f773: write of address 0xffffffc0'. Process Stopped. Use Step or Run to continue.
If I add __stdcall (after SCRAPER_API bool) in Scraper.cpp and Scraper.h, then the Delphi application doesn't start at all: The procedure entry point ScraperGetWinList could not be located in the dynamic link library Scraper.dll.
You need to put __stdcall after bool. The complete declaration, after all macros expand, should look like this:
extern "C"
{
__declspec(dllexport)
bool __stdcall ScraperGetWinList(SWin winList[100]);
}
EDIT: Looks like you'll also need a .def file there. It's a file that lists every function exported in the DLL, and in this case it's needed only to force C++ compiler not mangle the exported names. Contents would be this:
EXPORTS
ScraperGetWinList
I'm not sure which C++ compiler you're using, but normally you'd just specify the .def file along with .cpp; for example, the following works for VC++:
cl.exe foo.cpp foo.def
Also, you will need to tell Delphi to use stdcall as well, by inserting stdcall keyword right before external in your Delphi function declaration.
If you use a packed array[1..512] of char you will not need the ConvertToString() function.
"packed array of char" is assignment compatible with Delphi string (this goes back to very early forms of Pascal - packed array of char WAS the string type). You nmay need to scab the result for a null ($0) char to find the end of the C-string
Also what Delphi version are you using? if Delphi 2009 + you will need to use packed array[1..512] of AnsiChar ;
It would be good to know where exactly your access violation occurs. What variable/memory location is your runtime trying to access?
Then find out if this location should actually be accessible, and if so, why it's not.
My suspicion: you access an array element that isn't initialized correctly.
Index := 0;
S := ConvertToString(myWinList[Index].Title);
while S <> '' do
begin
WinListMemo.Lines.Add(S);
Inc(Index);
//////// Is Index pointing to a valid entry here? No check!
S := ConvertToString(myWinList[Index].Title);
end;
Either
the dll does not initialize it correctly,
or there is another way to find out the last element.
or you simply ran off the array altogether: the 101th element is also dereferenced. and the 102nd, if that memory location happens to contain a 0 character.
Check that the definition of your Delphi function matches what you are declaring the C++ function as too. In particular, make sure that you have stdcall at the end, and that your bool values are going to be consistent. C++ and Delphi use different values and sizes for bool, depending on the C++ compiler, so it may be better to use an appropriately sized Integer. As the size of the bool may not match the C++ size, this can affect the stack, and thus cause access violations.
[edited to remove mixed language duff response]