Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
TSDK
Nov 24, 2003

I got a wooden uploading this one
What you're looking for is some sort of factory class. My preferred method for registering class types to be created according to different types of string is to put a std::map into the factory that maps from strings to creator objects/function pointers.

Something like:
code:
class Widget;
typedef Widget (*WidgetCreator)();
class WidgetFactory
{
public:
    void RegisterWidget( std::string, WidgetCreator );
    Widget *Create( std::string );
private:
    std::map< std::string, WidgetCreator > m_registered_widgets;
};

class MyCustomWidget : public Widget
{
public:
    static Widget *Create() { return new MyCustomWidget(); }
};

...

m_widget_factory.Register( "MyCustomWidget", MyCustomWidget::Create );
Widget *p_custom_widget = m_widget_factory.Create( "MyCustomWidget" );
There's plenty of variations for the exact WidgetCreator type, and you can easily write a form that can be templatised so that you end up with the register call becoming something like:
code:
m_widget_factory.Create< MyCustomWidget >( "MyCustomWidget" );
which also negates the need to type in a Create function for each type of widget.

Adbot
ADBOT LOVES YOU

Fecotourist
Nov 1, 2008

heeen posted:

I want to make my classes scriptable, but I don't want to pollute everything with the script engine's implementation details. How do I handle callbacks with variable arguments nicely?
As in The to-be-scripted class has a function with some arguments that I want to be able to be called from v8 javascript for instance.
Since javascript is dynamically typed it calls with a list of vars, which might or might not be able to be casted to the actual expected arguments, and which might or might not be the right number of arguments.

Are you really committed to Javascript? If you can use Python, look into boost.python. It's really amazing how easily you can do "exotic" things like variadic member functions.

narfanator
Dec 16, 2008

Bitruder posted:

BUT -- how does this work exactly? Can I still have a list of Neuron types? How can the library know what models are available? Should the models somehow "register" with the library?

Any help on this would be great.

Thanks!

Yes, it should/can work. You want a base class that has all the functions things that deal with "Neurons" care about, some or most of which are virtual. (You can also make some abstract, which says to things; first, that you can never instantiate a Neuron, and second, that you can't instantiate a derived class unless it has it's own, non-abstract version of that function.)

Then you make derived classes, say "interneuron", that has it's own (defined) versions of all the virtual and/or abstract functions. (This is literally the exact same declaration, minus the virtual and abstract identifiers)

In your program, you then make a interneuron, and put it in a neuron slot. When the program goes "Okay, time to ask this neuron what it is...", it actually calls the interneuron's function, instead of the neuron's, due to the 'virtual'-ness of the function.

What you can't do is have a slot for a neuron, and try to call a function from interneuron that isn't in neuron; there's no way to guarantee that that function exists for that object; all that's guaranteed is that it's (at least) a neuron.

Example:

code:
class foo
{
   void doFooThing();
   virtual void doMyThing();
}

class bar
: public foo
{
   void doBarThing();
   void doMyThing();
}

int main(...)
{
   foo * pFoo = new foo();
   foo * pFakeFoo = new bar();

   pFoo->doFooThing(); //Calls this function for foo.
   pFoo->doMyThing();  //Since this is actually a foo object, calls the foo's function

// pFakeFoo->doBarThing(); Won't work! This is a pointer to a foo, so this function doesn't exist.
   pFakeFoo->doMyThing(); //But this isn't a foo object, and it's a virtual function. So we actually call Bar's version of the function.
}

edit: quotes, code

narfanator fucked around with this message at 20:13 on Mar 25, 2009

Luminous
May 19, 2004

Girls
Games
Gains

ShardPhoenix posted:

I can't figure out how to deal with 2D arrays. I have to make functions that can take and return 2D arrays of integers, but apparently functions in C++ can't return arrays as such, you have to return a pointer. This means that the functions have to take a pointer too, or they won't be composable in the way I need. However, I can't figure out how to actually do anything with an int**, like print it out. This is the code I have so far, but it segfaults whenever I try to dereference the pointer:

code:
snip
edit: I tried to declare an int** test2; and use that instead of the test array in the same way, but that also segfaulted when dereferencing when trying to initialize it.

I know you read the link the other guy posted and said it helped, but couldn't tell if you had actually found the solution to whatever you were doing.

Anyway, I cooked this very small example up that shows some ways you might use int**.

This is just test examples - you would want to keep proper track of things to keep in bounds, etc; you would also want to add in some error checking and cleanup, of course - I trust you can figure this part out.

code:
#include <iostream>

#define ROWS 4
#define COLS 6

int test[ROWS][COLS] = {{1,2,3,4,5,6},{7,8,9,0,1,2},{3,4,5,6,7,8},{9,0,1,2,3,4}};

int** create_block_from_block(int a_block[ROWS][COLS]);
int** create_block_from_block(int** a_block);
void print_block(int** a_block);

int main()
{

	int** a_dumb_block = create_block_from_block(test);
	print_block(a_dumb_block);
	std::cout << std::endl;

	int** another_dumb_block = create_block_from_block(a_dumb_block);
	print_block(another_dumb_block);

	return 0;

}

int** create_block_from_block(int a_block[ROWS][COLS])
{
	int** block = new int*[ROWS];
	for(int rows = 0; rows < ROWS; ++rows)
	{
		block[rows] = new int[COLS];
		for(int cols = 0; cols < COLS; ++cols)
		{
			block[rows][cols] = a_block[rows][cols];
		}
	}
	return block;
}

int** create_block_from_block(int** a_block)
{
	int** block = new int*[ROWS];
	for(int rows = 0; rows < ROWS; ++rows)
	{
		block[rows] = new int[COLS];
		for(int cols = 0; cols < COLS; ++cols)
		{
			block[rows][cols] = a_block[rows][cols];
		}
	}
	return block;
}

void print_block(int** a_block)
{
	for(int rows = 0; rows < ROWS; ++rows)
	{
		for(int cols = 0; cols < COLS; ++cols)
		{
			std::cout << a_block[rows][cols];
		}
		std::cout << std::endl;
	}
}

Luminous
May 19, 2004

Girls
Games
Gains

Zakalwe posted:

Sort of a side note. In C++ you can pass references to arrays. Not many people seem to know this.

void bar(int (&foo)[100]);

Only works for statically sized arrays, but at least foo doesn't degrade immediately into an int*.

Maybe a dumb question, but why would you do this? Arrays aren't copied when passed anyway, so what benefit does this serve?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Luminous posted:

Maybe a dumb question, but why would you do this? Arrays aren't copied when passed anyway, so what benefit does this serve?

Knowing (and/or asserting) the stride of a multi-dimensional array? length of an array.

By the way, for someone who claims to be helping someone understand the relationship between arrays and pointers, you don't seem to know much of what you're talking about, based on your code. (The first array subscript in a multi-dimensional array for function parameters always decays to a pointer. ROWS in a_block[ROWS][COLS] means exactly nothing).

Avenging Dentist fucked around with this message at 02:44 on Mar 27, 2009

Vanadium
Jan 8, 2005

Luminous posted:

Maybe a dumb question, but why would you do this?

To implement template<typename T, std::size_t N> std::size_t array_len(T(&)[N]) { return N; }

Luminous
May 19, 2004

Girls
Games
Gains
^^ edit: thanks Van, that's exactly the sort of answer I was looking for.

Avenging Dentist posted:

Knowing (and/or asserting) the stride of a multi-dimensional array?

By the way, for someone who claims to be helping someone understand the relationship between arrays and pointers, you don't seem to know much of what you're talking about, based on your code.

I never made that claim at all. Feel free to improve - nobody else gave any examples. I am assuming you are not meaning any of the things I mentioned I was not going to include in the example.

Also, no need to be snarky if you don't want to help. I asked a legitimate question to Zak (or anybody wanting to respond) - I wasn't being sarcastic to the guy at all. And your answer didn't clarify much (or your wording wasn't great).

Why void bar(int (&foo)[100]) instead of just void var(int foo[100])? What specifically does the former give us that the latter does not?

Luminous
May 19, 2004

Girls
Games
Gains

Avenging Dentist posted:

Knowing (and/or asserting) the stride of a multi-dimensional array? length of an array.

By the way, for someone who claims to be helping someone understand the relationship between arrays and pointers, you don't seem to know much of what you're talking about, based on your code. (The first array subscript in a multi-dimensional array for function parameters always decays to a pointer. ROWS in a_block[ROWS][COLS] means exactly nothing).

Are you trying to say the code I posted does not work, works by coincidence, or something else altogether? Because you're being exceptionally picky here if that is what you are focusing on. Yes, you can make the parameter a_block[][COLS]...what's your point? Is one more proper than the other (not a sarcastic question, see next sentence)? Now that you mention it, yeah, I can definitely see what I did as being misleading - but really, you could have said that without the 'tude, dude.

Luminous fucked around with this message at 03:02 on Mar 27, 2009

Zakalwe
May 12, 2002

Wanted For:
  • Terrorism
  • Kidnapping
  • Poor Taste
  • Unlawful Carnal Gopher Knowledge

Luminous posted:


Why void bar(int (&foo)[100]) instead of just void var(int foo[100])? What specifically does the former give us that the latter does not?

with int foo[100] foo is actually an int *.
with int (&foo)[100] foo is a reference to an array.

what does this mean? well for one thing the array carries things with it that a simple type* doesn't such as a size.

sizeof(foo) will return 4 and 400 respectively (assuming a 32 bit machine)

Luminous
May 19, 2004

Girls
Games
Gains

Zakalwe posted:

with int foo[100] foo is actually an int *.
with int (&foo)[100] foo is a reference to an array.

what does this mean? well for one thing the array carries things with it that a simple type* doesn't such as a size.

sizeof(foo) will return 4 and 400 respectively (assuming a 32 bit machine)

Ahhh, that is concise. Again, exactly what I was looking for. I haven't used sizeof in a long long time. Shockingly, it is not the first thing to come to my mind.

Thanks for the clarification :)

Zakalwe
May 12, 2002

Wanted For:
  • Terrorism
  • Kidnapping
  • Poor Taste
  • Unlawful Carnal Gopher Knowledge
code:

int bar[10]

const int (&foo() const)[10]
{
        return bar;
}

Here's another one along the same lines. Returning a const reference to an array of 10 integers. Syntax is a bit weird, but it works and is legal.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Luminous posted:

Are you trying to say the code I posted does not work, works by coincidence, or something else altogether? Because you're being exceptionally picky here if that is what you are focusing on. Yes, you can make the parameter a_block[][COLS]...what's your point? Is one more proper than the other (not a sarcastic question, see next sentence)? Now that you mention it, yeah, I can definitely see what I did as being misleading - but really, you could have said that without the 'tude, dude.

Providing incorrect/misleading examples of array->pointer decay in C/C++ is worse than providing no examples at all. It's one of the most common things that cause confusion among new programmers. In a function argument list,
code:
int foo[X][Y] == int foo[][Y] == int (*foo)[Y]
Note that the second (inner, in terms of memory organization) array bound remains, as the compiler needs to know the stride in order to know how far apart foo[i] and foo[i+1] are. However, the first (outer) array bound is lost because of pointer decay. Most people can handle array->pointer decay in the one-dimensional case, but the N-dimensional case is considerably harder for people to "get". Misleading information about this is poisonous and can stick around for much longer than it has any right to (for instance, cplusplus.com actually asserts that arrays are pointers).

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Avenging Dentist posted:

for instance, cplusplus.com actually asserts that arrays are pointers.
I had so many people tell me that when I was learning C++ :(

Ghotli
Dec 31, 2005

what am art?
art am what?
what.

Plorkyeran posted:

I had so many people tell me that when I was learning C++ :(

Color me uninformed. I have professors in school telling me to this day that arrays and pointers are one in the same. Anyone care to elaborate about how he is wrong on this one?

litghost
May 26, 2004
Builder

Plorkyeran posted:

I had so many people tell me that when I was learning C++ :(

There are many cases where arrays can decay into pointers, but they are different types. Perfect example:

code:
char * bufP;
char buffer[100];

sizeof(bufP); // = sizeof(void*)
sizeof(buffer); // = sizeof(char)*100

bufP = buffer; // Legal
buffer = bufP; // Not legal
There are also template tricks that you can do that require arrays, not pointers.

litghost fucked around with this message at 05:27 on Mar 27, 2009

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
This is the most fundamental difference between arrays and pointers; if you understand why it is true both formally and as a matter of data layout, then you pretty much grok the subject.

code:
void foo(char **myArray);

char x[5][6];
foo(x);  /*   <--- type error */

huge sesh
Jun 9, 2008

So, if you have something like char foo[3][3] is the data laid out by the compiler as identical to char foo[9]? i.e. foo[1][0] == foo[0][3]?

I can't believe I've been writing C/C++ for this long without knowing this.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

huge sesh posted:

So, if you have something like char foo[3][3] is the data laid out by the compiler as identical to char foo[9]? i.e. foo[1][0] == foo[0][3]?

I can't believe I've been writing C/C++ for this long without knowing this.

Yes.

dancavallaro
Sep 10, 2006
My title sucks
Can anyone point me in the direction of some resources on how to read from the serial port? If it matters, I think I'm going to do this in Linux because I have it in my head that it would be easier that way. I'm going to build a hardware random number generator that plugs into the serial port, so all I need to do is read bytes off the serial port, nothing fancy.

TSDK
Nov 24, 2003

I got a wooden uploading this one

dancavallaro posted:

Can anyone point me in the direction of some resources on how to read from the serial port? If it matters, I think I'm going to do this in Linux because I have it in my head that it would be easier that way. I'm going to build a hardware random number generator that plugs into the serial port, so all I need to do is read bytes off the serial port, nothing fancy.
Sure thing.

*nix systems generally make devices directly accessible as a virtual file, so you should be able to fopen the appropriate /dev file and use the normal stdio.h functions.

dancavallaro
Sep 10, 2006
My title sucks

TSDK posted:

Sure thing.

*nix systems generally make devices directly accessible as a virtual file, so you should be able to fopen the appropriate /dev file and use the normal stdio.h functions.

Doh, you mean I can literally just fopen("/dev/tty_", 'r') and then read bytes from there? I didn't realize it would be *that* easy..

TSDK
Nov 24, 2003

I got a wooden uploading this one

dancavallaro posted:

Doh, you mean I can literally just fopen("/dev/tty_", 'r') and then read bytes from there? I didn't realize it would be *that* easy..
There's probably a little more to it than that:
http://www.comptechdoc.org/os/linux/programming/c/linux_pgcserial.html

But basically it doesn't look all that tricky.

EDIT: Using Win32 is pretty easy as well, since you just go through COM:
http://www.codeproject.com/KB/system/SerialPortComm.aspx

TSDK fucked around with this message at 14:48 on Mar 27, 2009

dancavallaro
Sep 10, 2006
My title sucks
But to test it I should probably be able to do something like "od /dev/tty" on the appropriate tty device file, right? Thanks for the help, I think those two links should be perfect.

Mach Won
Jun 17, 2004

Is UNC playing? My post is either whining about (1) ref favoritism, (2) unfair recruiting/player caliber, (3) opposing team sucking or (4) the inevitable UNC win. The day you see me giving UNC credit for anything is the day someone hacked my account.

Roy era: 1-16 :qq: RIVALS!!!!!
I'm not sure if this is the right place for this question, but I'm trying to do some very basic TCP and UDP communication in C++ in Windows, and I'm really not sure where to start.

I'm having difficulty finding basic tutorials on Winsock stuff that I understand, so I'm wondering if there isn't a simpler way to do TCP and UDP communication.

Any advice?

TSDK
Nov 24, 2003

I got a wooden uploading this one

Mach Won posted:

I'm not sure if this is the right place for this question, but I'm trying to do some very basic TCP and UDP communication in C++ in Windows, and I'm really not sure where to start.

I'm having difficulty finding basic tutorials on Winsock stuff that I understand, so I'm wondering if there isn't a simpler way to do TCP and UDP communication.

Any advice?
This is about as gentle an introduction as there is:
http://www.codeproject.com/KB/IP/winsockintro01.aspx
http://www.codeproject.com/KB/IP/winsockintro02.aspx

fankey
Aug 31, 2001

Mach Won posted:

I'm not sure if this is the right place for this question, but I'm trying to do some very basic TCP and UDP communication in C++ in Windows, and I'm really not sure where to start.

I'm having difficulty finding basic tutorials on Winsock stuff that I understand, so I'm wondering if there isn't a simpler way to do TCP and UDP communication.

Any advice?
If you can use Managed C++, using the System.Net.Sockets classes is probably easier than straight WinSock.

Mach Won
Jun 17, 2004

Is UNC playing? My post is either whining about (1) ref favoritism, (2) unfair recruiting/player caliber, (3) opposing team sucking or (4) the inevitable UNC win. The day you see me giving UNC credit for anything is the day someone hacked my account.

Roy era: 1-16 :qq: RIVALS!!!!!
We don't really have any restrictions on what we can use, but I have no experience with .Net.

Winsock just seems like an awkward way to do all of this. All I'm doing is sending and receiving strings over TCP and UDP.

TSDK
Nov 24, 2003

I got a wooden uploading this one

Mach Won posted:

We don't really have any restrictions on what we can use, but I have no experience with .Net.

Winsock just seems like an awkward way to do all of this. All I'm doing is sending and receiving strings over TCP and UDP.
It's like a dozen lines of very simple, very basic code - exactly how easy do you need it to be?

Mach Won
Jun 17, 2004

Is UNC playing? My post is either whining about (1) ref favoritism, (2) unfair recruiting/player caliber, (3) opposing team sucking or (4) the inevitable UNC win. The day you see me giving UNC credit for anything is the day someone hacked my account.

Roy era: 1-16 :qq: RIVALS!!!!!

TSDK posted:

It's like a dozen lines of very simple, very basic code - exactly how easy do you need it to be?

I didn't mean that it was hard, just seemed messy compared to how I did TCP in MATLAB.

Thanks for the links. I'm reading through them.

fankey
Aug 31, 2001

Mach Won posted:

I didn't mean that it was hard, just seemed messy compared to how I did TCP in MATLAB.

Thanks for the links. I'm reading through them.
I won't sully the C++ thread with a bunch of managed C++ .Net code but if you want some example code email met at jhndnn at gmail dot com.

Vanadium
Jan 8, 2005

boost.asio is pretty neat too and more C++ish than raw sockets. On the other hand, it is a lot more C++ish than raw sockets.

Volte
Oct 4, 2004

woosh woosh
Managed C++ is a really stupid thing to use unless you're porting legacy C++ code to the .NET platform. If you are starting anew, you might as well just use C# in that case.

NickPancakes
Oct 27, 2004

Damnit, somebody get me a tissue.

Edit: nvm..

NickPancakes fucked around with this message at 00:20 on Mar 28, 2009

Bitruder
Nov 29, 2003

Majoring in connect the dots and colouring
I posted last page about how to write a plugin-architecture and so far things are going alright. I've got it so that I have libraries that I load dynamically with dlopen() and I'm able to create objects, but here's the particular problem I'm having:
code:
 class A {
  virtual void initialize() { cout << "IN A" << endl; }
  void init();
}
void A:init() {
  // Do stuff
  this->initialize();
}

//////////////////////////////////
// This is in the plugin library
class B: public A {
   void initialize();
}

void B:initialize() {
  // Do plugin specific initialization
  cout << "IN B" << endl;
}


/////////////////////////////////
// This is in my main program
A* p_plugin;
p_plugin = pluginfactory("B");
// p_plugin points to an instance of B now;
p_plugin->init();

// However, this outputs IN A.  WHY?
I have a feeling it's because p_plugin is of type A*, however, my main program doesn't know what "B" is called... so I have to use type A*. Any ideas what I can do here?

Thanks

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Your loaded libraries will need to register new plugin types with the central factory somehow, presumably during initialization.

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.
Could you show us the code for pluginfactory()? And what happens if you call initialize() directly?

Bitruder
Nov 29, 2003

Majoring in connect the dots and colouring
Here's the create() function in plugin factory that actually gives us the pointer.
code:
bool PluginFactory::create(std::string model_type, NeuronParams* np, Neuron* &n) {

    std::string library_name = "libdtnet_" + model_type + ".so";

    void* handle = dlopen(library_name.c_str(), RTLD_NOW);
    if (!handle) {
        std::cerr << "Cannot load library: " << dlerror() << std::endl;
        return false;
    }

    // reset errors
    dlerror();

    // load the symbols
    create_t* create_model = (create_t*) dlsym(handle, "create");
    const char* dlsym_error = dlerror();
    if (dlsym_error) {
        std::cerr << "Cannot load symbol create: " << dlsym_error << std::endl;
        std::cerr <<  "This does not appear to be a valid dtnet neuron model library." << std::endl;
        return false;
    }

    // create an instance of the class
    n = create_model();

    // copy in the parameters passed in if they are not null.
    if (np != NULL) n->params = *np;

    return true;
}
And here's a "create" function in a plugin called aEIF (so aEIF derives from the base class Neuron):
code:
extern "C" Neuron* create() {
    return new aEIF;
}

DividesByZero
Jan 24, 2006
Everything should be made as simple as possible, but no simpler

I have some n strings to read from input I want to store, where n is known. I want to store pointers to these strings in an array, so I can loop over it and do things with them, for example print them to output.

I wrote some test code;

code:
#include<stdio.h>
#include<stdlib.h>

void initialise(int, char *[]);
void prNames (int, char *[]);


int main()
{
	int n;
	
	scanf("%i",&n);
	
	char *names[n]; 
	initialise(n, names);
	prNames(n, names);

	return 0;
}

void initialise(int n, char *names[])
{
	int i;
	for (i=0;i<n;i++)
	{
		scanf("%s",names[i]);
	}

}


void prNames(int n,char *names[])
{	

	printf("prNames was called\n");
	int i;
	for(i=0;i<n;i++)
	{
		printf("%s\n",names[i]);
	}
}
Why doesn't this work? My understanding is that scanf allocates memory and stores the read object at the pointer provided as the second argument. That is scanf("%s",names[i]) should store the scanned in string at the location pointed to by the ith element of names. Where am I doing something dumb? Is it because names[i] is not actually pointing anywhere yet since it's not initialised when I do the scanf?

Adbot
ADBOT LOVES YOU

TSDK
Nov 24, 2003

I got a wooden uploading this one

DividesByZero posted:

Why doesn't this work? My understanding is that scanf allocates memory and stores the read object at the pointer provided as the second argument.
Your understanding is wrong:

http://www.cplusplus.com/reference/clibrary/cstdio/scanf.html posted:

The additional arguments should point to already allocated objects of the type specified by their corresponding format tag within the format string.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply