I have tried to streamline this, but if you need more detail or code, let me know.
First, some background: I am making a module for a C++ program using exported functions from a .dll to communicate with it. I do not have support from the original developer, so I do not have access to the source code, headers, .lib, or anything else. I used dependency walker to get a list of function names, and explicitly linked using getProcAddress with success on most functions. (Here is the solution I used to get this far.)
Now the problem I have run into is how to handle unknown structs. For example, I have access to the following equations:
foo::bar::bar(void)
struct foo::bar magic(void)
foo::baz::baz(struct foo::bar const &)
int foo::baz::qux(void)
So the top function is a constructor that makes an object with the same name as the struct. The second function is a magic function that outputs the struct with all the data in it. The third function is another constructor that makes a new object with that struct as an input. The final function outputs an integer value (what I really care about) with the object just created.
As you can see, I don't know, nor do I care what is in the struct. It just gets magically created and immediately passed to another function that deals with it. So here is how I attempted to handle it (look at the solution linked in the first paragraph if this doesn't make sense):
struct barStruct {
void** unknown1[1024];
void** unknown2[1024];
void** unknown3[1024];
};
typedef barStruct (*_magic) (char *);
typedef void (*_bazConstructor) (char *, struct barStruct const &);
typedef int (*_qux) (char *);
I think I figured out how many elements there are in barStruct because bazConstructor will crash if there are too many. The problem is, no matter what I have tried, qux will crash. I am guessing this has something to do with how I am handling barStruct. Is it necessary to define the struct like this? Is there a way to pass it directly from magic to the bazconstructor without trying to say what is in it?
Basically: How should I handle a struct if I have no idea what it is supposed to contain?
Related
Good evening!
I'm writing an Arduino library. Inside it, I want to instantiate an object from another library whose constructor needs to be passed a parameter, but I don't want to hard-code such parameter. I need some guidance about how to do this.
Here's the relevant part of my code so far:
HSBC_CAN.h:
class HSBC_CAN {
public:
HSBC_CAN(uint8_t, uint8_t);
private:
uint8_t _int_pin;
};
HSBC_CAN.cpp:
#include <HSBC_CAN.h>
#include <mcp_can.h>
extern MCP_CAN *canbus_esc;
HSBC_CAN::HSBC_CAN(uint8_t int_pin, uint8_t cs_pin) {
_int_pin = int_pin;
canbus_esc = new MCP_CAN(cs_pin);
}
To be clear, the way to instantiate an object from MCP_CAN class is MCP_CAN foo(int bar), where bar is the chip select pin number for SPI protocol. I want my library to instantiate an object of MCP_CAN class but I need to be able to pass the chip select pin number when instantiating an object from my new class HSBC_CAN. This is the error I get with the above code:
error: request for member 'begin' in 'canbus_esc', which is of pointer type 'MCP_CAN*' (maybe you meant to use '->' ?)
Probably the way I did in my sample code is totally wrong (with the extern keyword and the new operator) but that's just what came out from my mind ATM.
Thanks for the time.
The error message from the compiler is very useful and if you would follow its advice of replacing . with -> it would probably fix your immediate problem. Since canbus_esc is a pointer, you must dereference it before accessing its members or functions. So if it has a function named begin that can be called with zero arguments, you might write:
canbus_esc->begin();
That line is equivalent to:
(*canbus_esc).begin();
Also, get rid of the word extern on the line that defined canbus_esc, or else you will get an undefined reference error for it.
However, I have two issues with the code you have presented: First of all, you are using new, which does dynamic memory allocation. It's a good idea to avoid dynamic memory allocation on small devices like AVRs if you can, since you never know if those allocations are going to fail until you actually run the program (you might be using up too much memory in other parts of your program). Secondly, you defined your canbus_esc at the file scope, so there can only be one of them. This means you can't really create multiple HSBC_CAN objects; the second one will overwrite the canbus_esc create by the first. Although that might be fine for your application, it seems like a needless limitation.
I'd suggest writing your code like this instead:
Header file:
#include <mcp_can.h>
class HSBC_CAN {
public:
HSBC_CAN(uint8_t int_pin, uint8_t cs_pin);
void begin();
private:
uint8_t _int_pin;
MCP_CAN can;
};
Source file:
#include <HSBC_CAN.h>
HSBC_CAN::HSBC_CAN(uint8_t int_pin, uint8_t cs_pin)
: can(cs_pin) // This line constructs the MCP_CAN object
{
_int_pin = int_pin;
}
HSBC_CAN::begin()
{
can.begin(42, 42, 42); // TODO: fix arguments
}
Another idea, which might be better, would be for you to have your HSBC_CAN object take a pointer to an MBC_CAN object and store the pointer as a member variable in the HSBC_CAN class. That option would make a lot of sense if there are multiple devices on the CAN bus that you want to talk to using that MBC_CAN object. You could have multiple classes using a single MBC_CAN object via pointers.
Apologies in advance for noob mistakes. This is my first question here. First, some background:
I am trying to create a module for a program using dependency walker to find C++ functions in a .dll that I don't have the lib or any source code for. You can also assume that I can't get support from the original developer. Basically, I checked another file that accesses it to see what the minimum functions were to get it working. Here is an example of the undecorated names that are output:
void foo::bar::baz(float)
float foo::bar::qux(void)
foo::bar::bar(void)
class foo::bar & foo::bar::operator=(class foo::bar const &)
The top two functions obviously take float or void and return float or void. I got a similar function working using something like:
HINSTANCE THEDLL = LoadLibrary("C:\\dllFolder\\theDll.dll");
typedef float (*quxType)(void);
quxType qux = (quxType)GetProcAddress(THEDLL, "quxMangledName");
So those are not a problem.
Now, the third on the list looks like another function that takes void, but it doesn't have an explicit return type. Does this mean I should just use an implicit type for it, is it void, or is it not really a function? If not, what is it?
I have no idea what to do with the fourth one. Is it even possible to handle without the associated .h file?
I looked around, but I couldn't find any information on what to do when the function doesn't look like a normal function with an explicit return type. Despite using basically the same code that I used to get a function working in a similar .dll, I keep getting an access violation crash when I try to use function #2 here (I really just need function #2). So I am guessing that the .dll needs more information or needs something initialized first, which is why I am interested in the others on the list.
I realize this is a complicated problem, so there probably won't be a "Right answer" solution to get it working, but if I am making any obvious mistakes, or if there are any general suggestions for how to attack the problem (even alternatives to dependency walker), let me know.
The 3rd one is the default constructor of bar.
The 4th one is the copy assignment operator of bar.
I think you need to instantiate the class first, in order to call the 2nd method. Otherwise the method would be called with an invalid 'this' that causes access violation.
The problem is how you instantiate it?
If you can find a factory function that returns a bar in the DLL, you can try to use it.
If you don't see a factory function and you don't have the lib file, you can refer to answers here on how to create a lib from a DLL: How to make a .lib file when have a .dll file and a header file
You also need to create header file for the class, with the correct order and types of members. This way you don't have to use LoadLibrary and GetProcAddress, just use the class as normal.
You may still use LoadLibrary and GetProcAddress without the lib and header though, this blog shows how to manually allocate memory, call constructor, gets an object and pass that object to call a method: http://recxltd.blogspot.com/2012/02/working-with-c-dll-exports-without.html
This is for an assignment in my C class; I already have experience with C++. The issue I am having is that my implementation simply seems shady as hell. My current implementation only allows for one LinkedList to be used at a time. I know I can always just pass on a pointer to the structure, but I wanted to avoid that. Hence, it became really shady. I also have no way to regulate the scope of the functions; they are visible globally. Also notice that pointer to the structure in the h file; that is the reason why I can't have more than one in one program. Other than passing in the pointer to every function, can anyone think of another way?
It's only currently singly linked, but the Doubly Linked one won't take more than 30 minutes.
LinkedList.h
LinkedList.c
Yes, in C you will pass a pointer to a struct to every function that operates on it.
typedef struct list list_t;
list_t *list_new();
void list_delete(list_t *list);
void list_insert_back(list_t *list, void *obj);
void list_insert_front(list_t *list, void *obj);
/* etc. */
I'm not sure what you mean by "regulate the scope". If you are talking about function names, then you typically prefix the function names with a common prefix like list_ above.
Behind the scenes, this ends up working the same as C++ code. The C++ compiler prefixes member functions (like the example uses list_, although the C++ compiler does it differently), and the C++ compiler also passes the this parameter implicitly.
In fact, the very oldest C++ compiler (cfront) would translate C++ code directly into C code like the above.
Note that in contrast to the typical C++ method, you don't have to define the linked list structure in your header file -- this allows you to change the data structure without breaking ABI compatibility.
Since the rest of your question has been answered, I want to add that you can limit the scope of functions: simply declare them static, this will give them internal linkage:
/* This function won't be seen outside of the header file */
static void foo(list *l);
This is basically equivalent to declaring a private function foo in a class:
class list
{
private:
void foo();
};
Virtual table is arrary of function pointers.
How can i implement it as every function has different signature ?
You don't implement it.
The compiler generates it (or something with equivalent functionality), and it's not constrained by the type system so it can simply store the function addresses and generate whatever code is needed to call them correctly.
You can implement something vaguely similar using a struct containing different types of function pointer, rather than an array. That's quite a common way of implementing dynamic polymorphism in C; for example, the Linux kernel provides polymorphic behaviour for file-like objects by defining an interface along the lines of:
struct fileops {
int (*fo_read) (struct file *fp, ...);
int (*fo_write) (struct file *fp, ...);
// and so on
};
If functions in a virtual table have different signatures, you'll have to implement it as a structure type containing members with heterogeneous types.
Alternately, if you have other information telling you what the signatures are, you can cast a function pointer to another function pointer type, as long as you cast it back to the correct type before calling it.
If you know every function at compile time, then you could use a struct of differently typed function pointers (however, if you know every function at compile time, why wouldn't you just use a class with virtual methods?).
If you want to do this at runtime, then an array of void* would probably suffice. You'd need to cast the pointers in when you store them and out (to the correct type) again before you call them. Of course, you'll need to keep track of the function types (including calling convention) somewhere else.
Without knowing what you're planning to do with this it's very difficult to give a more useful answer.
There are valid reasons for implementing vtables in code. They're an implementation detail though, so you'll need to be targeting a known ABI rather than just 'C++'. The only time I've done this was an experiment to dynamically create new COM classes at runtime (the ABI expected of a COM object is a pointer to a vtable that contains functions following the __stdcall calling convention where the first 3 functions implement the IUnknown interface).
I've been writing a DLL in C++, now I must call this DLL from a VB6 application.
Here's a code sample from this DLL :
#include <vector>
#include <string>
using namespace std;
void __stdcall DLLFunction (vector<Object>*)
{
// performs a few operations on the Objects contained in the vector.
}
struct Object
{
long CoordX;
long CoordY;
long Width;
long Height;
LPSTR Id;
};
I also defined the "Object struct" in VB6
Private Type Object
CoordX As Integer
CoordY As Integer
Width As Integer
Height As Integer
Id As String
End Type
The issue is I don't know what vb6 type could stand for std::vector in order to call the DLL's function.
Notes :
- I use a vector for the DLL to be able to add objects.
- I use a pointer in order to use as less memory as possible.
- Sorry for my english, it ain't my home language at all.
- Thank you for reading and trying to help me.
Edit :
- I fixed the typing issues (Ids are definitely ended by NullChar, so LPSTR should do the trick).
- I read your answers, and I'd like to thank both of you, your answers are close to one another and a major issue remains. My DLL definitely needs to add elements to the container. Thus, I'm wondering how I could do the trick. Maybe I could add a return type to my function and then make that the function is able to return the items it created (instead of putting it directly into the container) so that the vb6 application gets these items and is able to process them, but I can't figure out how to do this
Edit bis :
#Rook : I feel like I could achieve this by using a new struct.
struct ObjectArrayPointer
{
Object* Pointer;
size_t Counter;
}
And then call my function this way :
void __stdcall DLLFunction (ObjectArrayPointer*);
I would then be able to add objects and edit the size parameter for my VB6 application to find these new objects. Was that what you meant?
You should not be trying to export template containers from a DLL anyway. They're likely to break when faced with newer compilers and libraries (eg. a library built under C++03 will not play well with code built using C++11).
The least painful thing to do is to accept a pointer to a buffer and a length parameter,
void __stdcall DLLFunction (Object* buffer, size_t nObjects);
if the size of the container will not change during execution. This interface is about as simple as it gets, and is easily accessible by any language that understand C calling conventions (eg. almost every single one.)
You've already thrown away most of the use of a std::vector because you've already specialised it to Object; you could consider going all the way and creating your own ObjectCollection class which uses a std::vector internally but presents a non-templated interface. Here's a simple example :
// In your public API header file:
typedef struct object_collection_t *object_collection;
object_collection CreateObjectCollection();
void DestroyObjectCollect(object_collection collection);
void AddObjectToCollection(object_collection collection, Object* object);
// etc
No template types are exposed in any form in the header. This is good.
// And the corresponding code file:
struct object_collection_t
{
std::vector<Object*> objects;
};
object_collection CreateObjectCollection() { return new object_collection_t; }
void DestroyObjectCollect(object_collection collection) { delete collection; }
void AddObjectToCollection(object_collection collection, Object* object)
{
collection->objects.push_back(object);
}
// etc
All of templating code is hidden away, leaving you with a fairly clean and simple interface which present an opaque pointer type that can be passed around by external code but only queried and modified by your own, etc.
EDIT: Incidentally, I've used Object* throughout the above code. It may well be safer and impler to use just plain old Object and avoid all of the issues associated with memory management and pointer manipulation by client code. If Object is sufficiently small and simple, passing by value may be a better approach.
(NB: not checked for compilability or functionality. E&OE. Caveat Implementor!)
You can't do that as it's a C++ class/template. Internally, it's an array but not in a way that can be created from VB6.
Your best bet is to change the function to accept a pointer to an array with a count parameter.
You'll also need to be very careful as to how the type is structured.
C++ ints are Longs in VB6.
Also, the Id string won't be compatible. VB6 will have a pointer to a unicode BString (unless you make it fixed length) where as a C++ will have std::string which is an array of ANSI chars. VB6 MAY marshal this if you pass an array of the objects (rather than a pointer)
The VB6 ABI is the COM Automation ABI.
Therefore, if you need an arry which is VB6 ABI compatible, you should probably use SAFEARRAY. I suggest you should also be using the Compiler COM Support classes:
http://msdn.microsoft.com/en-US/library/5yb2sfxk(v=vs.80).aspx
This question appears to do exactly what you want, using ATL's CComSafeArray class:
conversion between std::vector and _variant_t
You may also want to look at these:
https://stackoverflow.com/search?q=safearray+_variant_t
Alternatives to SAFEARRAY
The alternative to SAFEARRAY is to supply a COM Collection object. This is simply a COM object with a Dispinterface or Dual interface with the methods Count and Item. Item should have dispid=0 to be the default method. You may also want to supply _NewEnum with DISPID_NEWENUM to support the For Each syntax.