Page 1 of 1

weird error when calling extern "c" from C++

Posted: Mon Jul 09, 2007 6:54 am
by AndrewAPrice
I'm getting these errors:

Code: Select all

port.cpp: In member function 'unsigned char Port::InByte(short unsigned int)':
port.cpp:16: error: expected unqualified-id before string constant
port.cpp: In member function 'void Port::OutByte(short unsigned int, unsigned char)':
port.cpp:25: error: expected unqualified-id before string constant
Both errors point to the line:

Code: Select all

extern "C"
Here is my port.h:

Code: Select all

#ifndef PORT_H
#define PORT_H

class Port
{
public:
    Port();
    ~Port();
    unsigned char InByte(unsigned short _port);
    void OutByte(unsigned short _port, unsigned char _data);
private:
};

extern Port port;
#endif
and here is my port.cpp:

Code: Select all

#include "port.h"

Port port;

Port::Port()
{
}

Port::~Port()
{
}

unsigned char Port::InByte(unsigned short _port)
{
    unsigned char rv;
    extern "C"
    {
        __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
    }
    return rv;
}

void Port::OutByte(unsigned short _port, unsigned char _data)
{
    extern "C"
    {
        __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
    }
}
It's being passed to gcc using

Code: Select all

gpp -c port.cpp -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions
I don't understand why it's doing this. I've used C in C++ before.

Posted: Mon Jul 09, 2007 7:05 am
by AndrewAPrice
I solved it. I read on an IBM website that you can't use extern "C" from within a class member function. I used a simple C wrapper like so:

Code: Select all

extern "C"
{
    unsigned char port_inbyte(unsigned short _port)
    {
        unsigned char rv;
        __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
        return rv;
    }
}

unsigned char Port::InByte(unsigned short _port)
{
    return port_inbyte(_port);
}
and now it works :)

Posted: Wed Jul 11, 2007 1:08 am
by JamesM
You don't need extern "C" there in the first place: inline asm works from C++ member functions. Extern "C" is only used if you need to change the calling convention from __thiscall to __cdecl (no "this" pointer to pass).