Thread: References

  1. #1
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034

    Smile References

    Hey.. ya.. I still find safe conversion between references and pointers vague. I've been meaning to read more, but I haven't had any problems, and I can't always tell if the code is flawed. This is the kind of fundamental knowledge I know there will be comments.

    Let's take for example a custom struct used for the cURL write callback (4th parameter - userp).

    In this case inside write_data should I just convert userp to a CData pointer and use it as a pointer instead of dereferencing it? Do I need another -if- check on the pointer after converting to CData and before dereferencing it? Also should I instead create cdata dynamically instead, when passing it to curl_easy_setopt (instead of passing the reference)? I guess it would depend if the object goes out of scope and is destroyed? Opinions please and thanks again!

    Code:
    struct CData
    {
    	std::string Host;
    	unsigned int Port;
    };
    
    size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp)
    {
    	if(userp)
    	{
    		CData& cdata = *(CData*)userp;
    
    		std::cout << cdata.Host << ":" << cdata.Port << std::endl;
    	}
    
    	return nmemb;
    }
    
    
    //later in main()
    CData cdata;
    
    cdata.Host = "google.com";
    cdata.Port = 80;
    
    //later in main()
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &cdata);
    Last edited by Dae; 07-23-2009 at 02:03 AM.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Looks fine to me.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Dae
    In this case inside write_data should I just convert userp to a CData pointer and use it as a pointer instead of dereferencing it?
    I think that that is a matter of personal preference. Either way, consider using reinterpret_cast instead of a C-style cast when casting from void* to CData*.

    Quote Originally Posted by Dae
    Do I need another -if- check on the pointer after converting to CData and before dereferencing it?
    No.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Deprecated Dae's Avatar
    Join Date
    Oct 2004
    Location
    Canada
    Posts
    1,034
    Thanks guys. Appreciate it!

    I don't expect a response about this, because it's a rather strange question:

    Since it relates to the OP code, I'd like to ask if there is a way to convert a class method to act like a C function? (handle/remove "this" parameter before being invoked). I've attempted boost::bind.

    I ask because I'd rather pass cURL a class method instead of a function.

    Code:
    class Request
    {
    public: 
    	Request(std::string const& url)
    	{
    		//later in constructor
    		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, boost::bind(&Request::OnReadContent, this, _1, _2, _3, _4));
    	}
    
    	size_t OnReadContent(void *buffer, size_t size, size_t nmemb, void *userp)
    	{
    		std::cout << "OnReadContent" << std::endl;
    
    		return nmemb;
    	}
    };
    If it's not possible.. that's fine. I only ask because the error intrigues me:

    Run-Time Check Failure #0 - The value of ESP was not properly saved across the function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
    So then it's complaining that it's defined as __thiscall, when cURL calls it as __stdcall or __cdecl? (ie. the typedef below). From the library source, the error line:

    Code:
    size_t wrote = data->set.fwrite_func(ptr, 1, len, data->set.out);
    Calling a method of object set which is operator() of boost::bind which calls a method of class Request? I can see how that could cause problems. The typedef for the function it's calling is:

    Code:
    typedef size_t (*curl_write_callback)(char *buffer,
                                          size_t size,
                                          size_t nitems,
                                          void *outstream);
    So perhaps some sort of cast from boost::bind or Request::OnReadContent(this, x, x, x, x) to curl_write_callback? or some sort of preprocessor?

    Of course I could make it static... and pass -this- as the 4th parameter, but like I said.. I was curious.
    Warning: Have doubt in anything I post.

    GCC 4.5, Boost 1.40, Code::Blocks 8.02, Ubuntu 9.10 010001000110000101100101

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Since it relates to the OP code, I'd like to ask if there is a way to convert a class method to act like a C function? (handle/remove "this" parameter before being invoked). I've attempted boost::bind.

    No, you shouldn't pass the curl API anything other than a function with that exact signature.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It's possible, but you should absolutely not pass an object to C code.
    This nice trick is reserved for C++ code that takes a functor as argument.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> It's possible, but you should absolutely not pass an object to C code.

    That's a little misleading, though. You can't simply because the callback function has to be in that format. And you can pass a C++ object to a C callback function, since the C code doesn't know or care what you do with the object once the callback is invoked.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If you must pass an object into C code, it should be done via a pointer (void*).
    That is, you must probably allocate it on the heap or somewhere where it doesn't go out of scope and pass that along as a void* pointer to C code.
    But since the code doesn't expect a void* pointer, it's dangerous to do so. Never pass an object in any way to a C function that will manipulate this object. You'll be treading into undefined behavior then.
    If the function simply passes on the void* pointer or the like, then it's okay.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiler settings, references etc...
    By ejohns85 in forum C++ Programming
    Replies: 0
    Last Post: 05-14-2009, 04:53 AM
  2. VC++ 2005 Express: missing references page
    By psychopath in forum Tech Board
    Replies: 1
    Last Post: 08-21-2006, 04:55 PM
  3. Arrays of references
    By Welshy in forum C++ Programming
    Replies: 16
    Last Post: 07-04-2005, 11:28 PM
  4. declare references to references works!
    By ManuelH in forum C++ Programming
    Replies: 4
    Last Post: 01-20-2003, 08:14 AM
  5. Pointers and references...
    By SushiFugu in forum C++ Programming
    Replies: 6
    Last Post: 12-08-2001, 04:21 PM