I have a struct, file, and a class with functions in it. I'm trying to create a linked list of structs in my function, but I can't quite understand how to go about doing it! Here's my work thus far for that portion of my code:
#include <iostream>
using namespace std;
class myPrintSpool
{
public:
void send(string);
private:
int printSpoolSize;
myPrintSpool *printSpoolHead;
myPrintSpool* next;
};
struct file
{
string fileName;
int filePriority;
file* next;
};
void myPrintSpool::send(string name)
{
//Adds to linked list
file file;
myPrintSpool* file = new myPrintSpool;
if(printSpoolHead == NULL)
{
printSpoolHead = file;
}
else
{
file->next = printSpoolHead;
printSpoolHead = file;
}
printSpoolSize++;
}
I send a string inside the function so that when the user inputs a file name to send, it changes the name of the struct to that fileName in struct file changes to that input name. However, I'm not sure what to do since I cannot get the above portion to work properly first.
Thank you in advance, and thank you for taking the time to help me out!
It's been a while since I've done any C++, so this is all from recollection. In the code you supplied, you aren't instantiating a class. You are allocating memory for one.
If you want to assign a new class to that memory:
myPrintSpool printSpool = new myPrintSpool();
myPrintSpool *file = &printSpool;
I'm somewhat confused as to what you are actually doing. It seems the printSpoolHead will always be equal to the current myPrintSpool object, and if it's anything other than the first instantiation, it points back to itself.
As you didn't say anything specific as to the location of your error(s), do a simple output to verify the function is doing what you think it should (or is) doing.
Edit: Actually, I recall being thrown off by C++ instantiation, so it may be:
myPrintSpool printSpool;
Related
Consider the following code:
Automobile.h
class Automobile
{
static string m_stCityCode;
static bool CheckCityCode(const Automobile& obj);
};
Automobile.cpp
bool Automobile::CheckCityCode(const Automobile& obj)
{
return m_stCityCode == obj.m_stCityCode;
}
int main()
{
//do something
}
I get the following error
"Severity Code Description Project File Line Suppression State
Error LNK2001 unresolved external symbol "public: static class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> > Automobile::m_stCityCode"
(?m_stCityCode#Automobile##2V?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##A) myPro C:\Users\zhivko.rusev\Documents\Visual
Studio 2015\Projects\myPro\myPro\Calls.obj 1 "
I would appreciate every help for solving this problem. Thanks in advance!
The static member needs to be defined. The error message is the linker's way of telling you it isn't. Your code declares the static member but does not define it.
To define it, in a single compilation unit (i.e. a non-header source file) simply add a line at file scope after including the header file
#include "Automobile.h"
std::string Automobile::m_stCityCode = ""; // change the initialiser to whatever suits
Do this in exactly one compilation unit. One is necessary to define the symbols. Multiple definitions (e.g. in multiple source files within your project) will cause the linker to complain about symbols being defined multiple times.
There are other problems in your code as shown, beyond what you have asked about, but I'll assume that just reflects you having left information out.
I am doing a C++/CX runtime wrapper, and I need pass C++/CX Object pointer to native C. How do I do it, and convert the native pointer back to C++/CX Object reference type?
void XClassA::do(XClass ^ B)
{
void * ptr = (void*)(B); // how to convert it?
}
And also, C++/CX uses Reference Counting, if I cast the Object reference to native pointer, how do I manage the pointer life cycle?
update (request from #Hans Passant)
Background of the question,
Native C
I am trying to use C++/CX wrap Native C library (not C++) as Windows Runtime Component. Native c has many callback functions which declared as the following,
for example,
//declare in native c
typedef int (GetData*)(void *, char* arg1, size_t arg2);
void * is a pointer to object instance.
and the callback will be executed in native c during runtime.
We expect Application(C#/C++CX ...) to implement the method.
WinRT wrapper (C++/CX)
my idea is the following,
(1) Provide interface to Application
// XRtWrapperNamespace
public interface class XWinRtDataWrapper
{
//declare in base class
void getData(IVector<byte> ^ data);
}
to let Application implement the function. As I cannot export native data type, I provide IVector to get data from Application.
(2) Declare a global callback function to convert IVector<byte>^ to native data type char *, like following,
// when Native C executes callback function,
// it will forward in the method in C++/CX.
// The method calls the implementation method via object pointer.
// (And here is my my question)
void XRtWrapperNamespace::callbackWrapper(void * ptr, char *, int length)
{
// create Vector to save "out" data
auto data = ref new Vector<byte>();
// I expect I could call the implementation from Application.
ptr->getData(data); // bad example.
// convert IVector data to char *
// ...
}
My question is
How do I keep windows object reference to native C?
It looks impossible, but any solution to do it?
Application (example)
//Application
public ref class XAppData: public XWinRtDataWrapper
{
public:
virtual void getData(IVector<byte> ^ data)
{
//implementation here
}
}
You are not on the right track. I'll assume you #include a c header in your component:
extern "C" {
#include "native.h"
}
And this header contains:
typedef int (* GetData)(void* buffer, int buflen);
void initialize(GetData callback);
Where the initialize() function must be called to initialize the C code, setting the callback function pointer. And that you want the client code to directly write into buffer whose allocated size is buflen. Some sort of error indication would be useful, as well as allowing the client code to specify how many bytes it actually wrote into the buffer. Thus the int return value.
The equivalent of function pointers in WinRT are delegates. So you'll want to declare one that matches your C function pointer in functionality. In your .cpp file write:
using namespace Platform;
namespace YourNamespace {
public delegate int GetDataDelegate(WriteOnlyArray<byte>^ buffer);
// More here...
}
There are two basic ways to let the client code use the delegate. You can add a method that lets the client set the delegate, equivalent to way initialize() works. Or you can raise an event, the more WinRT-centric way. I'll use an event. Note that instancing is an issue, their is no decent mapping from having multiple component objects to a single C function pointer. I'll gloss this over by declaring the event static. Writing the ref class declaration:
public ref class MyComponent sealed
{
public:
MyComponent();
static event GetDataDelegate^ GetData;
private:
static int GetDataImpl(void* buffer, int buflen);
};
The class constructor needs to initialize the C code:
MyComponent::MyComponent() {
initialize(GetDataImpl);
}
And we need the little adapter method that makes the C callback raise the event so the client code can fill the buffer:
int MyComponent::GetDataImpl(void* buffer, int buflen) {
return GetData(ArrayReference<byte>((byte*)buffer, buflen));
}
The problem involved a JAVA call to a C-function (API) which returned a pointer-to-pointer as an argout argument. I was trying to call the C API from JAVA and I had no way to modify the API.
Using SWIG typemap to pass pointer-to-pointer:
Here is another approach using typemaps. It is targetting Perl, not Java, but the concepts are the same. And I finally managed to get it working using typemaps and no helper functions:
For this function:
typedef void * MyType;
int getblock( int a, int b, MyType *block );
I have 2 typemaps:
%typemap(perl5, in, numinputs=0) void ** data( void * scrap )
{
$1 = &scrap;
}
%typemap(perl5, argout) void ** data
{
SV* tempsv = sv_newmortal();
if ( argvi >= items ) EXTEND(sp,1);
SWIG_MakePtr( tempsv, (void *)*$1, $descriptor(void *), 0);
$result = tempsv;
argvi++;
}
And the function is defined as:
int getblock( int a, int b, void ** data );
In my swig .i file. Now, this passes back an opaque pointer in the argout typemap, becaust that's what useful for this particular situation, however, you could replace the SWIG_MakePtr line with stuff to actually do stuff with the data in the pointer if you wanted to. Also, when I want to pass the pointer into a function, I have a typemap that looks like this:
%typemap(perl5, in) void * data
{
if ( !(SvROK($input)) croak( "Not a reference...\n" );
if ( SWIG_ConvertPtr($input, (void **) &$1, $1_descriptor, 0 ) == -1 )
croak( "Couldn't convert $1 to $1_descriptor\n");
}
And the function is defined as:
int useblock( void * data );
In my swig .i file.
Obviously, this is all perl, but should map pretty directly to Java as far as the typemap architecture goes. Hope it helps...
[Swig] Java: Using C helper function to pass pointer-to-pointer
The problem involved a JAVA call to a C-function (API) which returned a pointer-to-pointer as an argout argument. I was trying to call the C API from JAVA and I had no way to modify the API.
The API.h header file contained:
extern int ReadMessage(HEADER **hdr);
The original C-call looked like:
HEADER *hdr;
int status;
status = ReadMessage(&hdr);
The function of the API was to store data at the memory location specified by the pointer-to-pointer.
I tried to use SWIG to create the appropriate interface file. SWIG.i created the file SWIGTYPE_p_p_header.java from API.h. The problem is the SWIGTYPE_p_p_header constructor initialized swigCPtr to 0.
The JAVA call looked like:
SWIGTYPE_p_p_header hdr = new SWIGTYPE_p_p_header();
status = SWIG.ReadMessage(hdr);
But when I called the API from JAVA the ptr was always 0.
I finally gave up passing the pointer-to-pointer as an input argument. Instead I defined another C-function in SWIG.i to return the pointer-to-pointer in a return value. I thought it was a Kludge ... but it worked!
You may want to try this:
SWIG.i looks like:
// return pointer-to-pointer
%inline %{
HEADER *ReadMessageHelper() {
HEADER *hdr;
int returnValue;
returnValue = ReadMessage(&hdr);
if (returnValue!= 1) hdr = NULL;
return hdr;
}%}
The inline function above could leak memory as Java won't take ownership of the memory created by ReadMessageHelper, since the HEADER instance iscreated on the heap.
The fix for the memory leak is to define ReadMessageHelper as a newobject in order for Java to take control of the memory.
%newobject ReadMessageHelper();
JAVA call now would look like:
HEADER hdr;
hdr = SWIG.ReadMessageHelper();
If you are lucky, as I was, you may have another API available to release the message buffer. In which case, you wouldn’t have to do the previous step.
William Fulton, the SWIG guru, had this to say about the approach above:
“I wouldn't see the helper function as a kludge, more the simplest solution to a tricky problem. Consider what the equivalent pure 100% Java code would be for ReadMessage(). I don't think there is an equivalent as Java classes are passed by reference and there is no such thing as a reference to a reference, or pointer to a pointer in Java. In the C function you have, a HEADER instances is created by ReadMessage and passed back to the caller. I don't see how one can do the equivalent in Java without providing some wrapper class around HEADER and passing the wrapper to the ReadMessage function. At the end of the day, ReadMessage returns a newly created HEADER and the Java way of returning newly created objects is to return it in the return value, not via a parameter.”
I'm a beginner to C++ programming, and I'm wondering how you would go about passing a struct as an argument to a function using cin.
The idea of the code is to input the name of a struct from the user, and have that name be passed to a function. Here's what I've been playing around with:
class myPrintSpool
{
public:
myPrintSpool();
void addToPrintSpool(struct file1);
private:
int printSpoolSize();
myPrintSpool *printSpoolHead;
};
struct file1
{
string fileName;
int filePriority;
file1* next;
};
int main()
{
myPrintSpool myPrintSpool;
myPrintSpool.addToPrintSpool(file1);
return 0;
}
This is able to build. However, I wanted something more along the lines of:
class myPrintSpool
{
public:
myPrintSpool();
void addToPrintSpool(struct fileName);
private:
int printSpoolSize();
myPrintSpool *printSpoolHead;
};
struct file1
{
string fileName;
int filePriority;
file1* next;
};
int main()
{
string fileName;
cout << "What is the name of the file you would like to add to the linked list?";
cin >> fileName;
myPrintSpool myPrintSpool;
myPrintSpool.addToPrintSpool(fileName);
return 0;
}
Can anyone help how I would go about doing this? Thanks in advance!
This sort of metaprogramming is, in general, extremely advanced in C++. The reason is, unlike interpreted languages, much of what exists in the source file is lost when the file is compiled. In the executable, the string file1 may not show up at all! (it's implementation dependent, I believe).
Instead, I would recommend doing some sort of lookup. For instance, you can compare the string passed in in fileName to each struct's fileName, or, you can just associate any key with your struct. For instance, if you created a std::map<string, baseStruct*> and inherited all of your structs (e.g. file1, file2, ...) from baseStruct, then you can lookup in the map which struct is associated with the passed in string. The inheritance is important, because you will need polymorphism to insert structs of differing types into the map.
There are many other, more advanced topics that we could get into, but this is the general idea. It's most simple to do some sort of lookup rather than try to instantiate a type at runtime from a string. Here is a more rigorous and more maintainable approach to doing basically the same thing.
EDIT: If you mean you have only one type of struct called 'file1' and you want to instantiate it and pass it to addToPrintSpool, that's different than my previous answer (which applies if, for example, you want to have multiple structs called file1 and file2 and want to infer which struct to use. Figuring out types dynamically from a string is hard, but setting the string in an instance of a known type is straightforward.)
To instantiate and use an instance of file1 you can do this:
//In myPrintSpool, use this method signature.
//You are passing in an object of type file1 named aFile;
//note that this object is _copied_ from someFile in your
//main function to a variable called aFile here.
void addToPrintSpool(file1 aFile);
...
int main()
{
string fileName;
cout << "What is the name of the file you would like to add to the linked list?";
cin >> fileName;
//Instantiate a file1 object named someFile, which has all default fields.
file1 someFile;
//Set the filename of aFile to be the name you read into the (local) fileName var.
someFile.fileName = fileName;
myPrintSpool myPrintSpool;
//Pass someFile by value into addToPrintSpool
myPrintSpool.addToPrintSpool(someFile);
return 0;
}
Apologies for not being familiar with formatting on here...I've made
some progress thanks to helpful replies and edited and removed my original
question to be replaced by the current one.
My problem lies with converting a C struct or struct pointer to PyObject. There
is no alternative to this because I am wrapping an existing C library whose
callback requires a C struct pointer.
Following works but with limitations:
%module cain1
%{
typedef struct {
double price;
int volume;
} book_entry_t;
typedef struct {
char symbol[10];
book_entry_t *book;
} trade_t;
typedef void (*CALLBACK)(trade_t trade);
CALLBACK my_callback = 0;
static PyObject *my_pycallback = NULL;
static void bigSnake(trade_t trade)
{
PyObject *result;
PyObject *d1;
result = PyEval_CallObject(my_pycallback,
Py_BuildValue("(y#)",
(char*)&trade,
sizeof(trade_t)
)
);
Py_XDECREF(result);
return /*void*/;
}
void test_cb (PyObject *callMe1) {
trade_t d1;
book_entry_t b1;
b1.price = 123.45;
b1.volume = 99;
Py_XINCREF(callMe1); /* Add a reference to new callback */
my_pycallback = callMe1; /* Remember new callback */
strcpy (d1.symbol,"Gupta Ltd");
d1.book = &b1;
bigSnake(d1);
}
%}
// Expose in python module..
typedef struct {
double price;
int volume;
} book_entry_t;
typedef struct {
char symbol[10];
book_entry_t *book;
} trade_t;
void test_cb(PyObject *callMe1);
and then triggering the callback from Python:
import cain1
import struct
def dave(d1):
N1,N2 = struct.unpack('10sP', d1)
print ('\n %s: %x' % (N1.decode() ,N2))
price,volume = struct.unpack('di',N2)
print (price,volume)
def main():
cain1.test_cb(dave)
main()
but I am unable to recover the book_entry_t strcut contents pointed to by trade_t....
I just feel this is all too convoluted since I have the pointer to structs and there
must be a straightforward way for Python to use that without any fuss.
Py_BuildValue("(N)",details) expects a PyObject* (your "N" says so), and you pass it something very different. Try Py_BuildValue("(i)", details.index) instead, and change it to accomodate any changes in details_t.
You're attempting to build a PyObject from a details_t struct. This isn't valid. Either pass the callback an integer (seems easier since details_t only has the one field) OR create a proper PyObject type. You can't blindly cast one type to another and expect it to work (a PyObject is more than just a pointer).