C++ Gurus - Is C++ a good choice for public API(s)??? Are there cleanways to solve known problems th

Discussion in 'C++' started by arijit79@gmail.com, May 31, 2009.

  1. Guest

    Hi

    I needed to build up a public API for an application at hand.

    The data I am modelling maps very well to object oriented design, so I
    am little inclined towards a C++ public API (i.e. my deliverables
    would be a <xyz>.hpp file which will have a bunch of pure virtual
    functions forming the interface and a lib<xyz>.so which will basically
    contain the implementation for those interfaces).

    But, I can think of 2 problems there:
    1) How do I guarantee that my shared library will work well with the
    version of the C++ library/compiler my customer/user is having?
    Issue in detail: I mean, I compile my shared library with version 'X'
    of a Std CPP compiler and customer tries to use with version 'Y' of
    StdCPP compiler. And then, if 'X' and 'Y' versions of CPP compiler are
    not compatible, then we get into trouble. We have hit this several
    times with different gcc versions. Just wondering, what is the best/
    cleanest way to solve/get-around this problem?

    2) Sometimes it happens that you are working on a C++ based product
    which already has millions of lines of code and then, one fine day a
    requirement comes that a part of that chunk needs to be made accesible
    to users through a shared library. Now, which you work towards
    building that shared library, you may want to ensure that only symbols
    that *should be* exported to users/customers, needs to be exported in
    the shared library, all others un-wanted globals should not be
    exported in the shared library to ensure we don't un-necessarily
    pollute customer's namesapce with whole lot of our internal/global
    symbols. (Note: Ideal solution for this issue, probably would be to
    ensure that we should never pollute our implementation namespace at
    all, in the first place, but as I said, you may not be the one who had
    written all these code and it's a million lines code, and you don't
    have the option/bugdet for re-arch/re-write!). For such a requriement,
    if it was a C library we could typically use 'objcopy' in linux or -M
    compiler option in Solaris, to make sure only a given set of symbols
    (defined by us) are made global. But if it's a C++ library, I wonder
    how to achieve this goal?
    Issues: C++ symbols are mangled, so I would probably need to specify
    those mangled names as an input to 'objcopy', but mangling varies from
    compiler to compiler and platform to platform. With that this can
    become a real maintenance headache.

    Question: Is there a cleaner/better way to handle this?

    Thanks in advance for oyour time and help!

    Arijit
    , May 31, 2009
    #1
    1. Advertising

  2. Phlip Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are thereclean ways to solve known problems there?

    wrote:

    > I needed to build up a public API for an application at hand.


    You cannot do any of this by guessing or planning. To create a public API, you
    must write at least three projects, and port them to three different platforms
    (linux, mac & pc) come to mind. Then you must configure your unit tests to run
    simultaneously on each of the three platforms, each time you save your code. (I
    have done this before, between Linux & PC, using Samba. Both platforms compiled
    simultaneously into the same folders.)

    Your nine projects should run all their tests each time you edit any of their
    sources - both inside and outside the API boundary. And you write three
    different projects to prove that your API actually solves problems for them,
    flexibly.

    > The data I am modelling maps very well to object oriented design, so I
    > am little inclined towards a C++ public API (i.e. my deliverables
    > would be a <xyz>.hpp file which will have a bunch of pure virtual
    > functions forming the interface and a lib<xyz>.so which will basically
    > contain the implementation for those interfaces).


    That's not what "pure virtual" means. It means the methods _don't_ have
    implementations. If you go this route, you will simply need virtual methods.
    However...

    Why do you think the project will need an OO design? The point of OO is to
    abstract and vary virtual methods behind common interfaces. Have you written any
    sample code showing the best places for the virtual methods? They might not be
    what you expect.

    You might be safer - if your client actually _needs_ all these platforms - by
    writing a C-style API. The C++ communities widely support this technique,
    because most platforms enforce compatibility standards among simple functions.
    By contrast, because C++ virtual methods must be very optimal, they enjoy fewer
    standards. You might not be able to ship binaries, for example, and you might
    have to ship live source code for your clients to compile.

    > But, I can think of 2 problems there:
    > 1) How do I guarantee that my shared library will work well with the
    > version of the C++ library/compiler my customer/user is having?


    By actually getting all the versions, like I said, and constantly testing them
    as you change the code. If you make a change that you think is innocent, and if
    one platform throws up a red flag, you can back out the change long before you
    commit to it and invest more code around it.

    > Issue in detail: I mean, I compile my shared library with version 'X'
    > of a Std CPP compiler and customer tries to use with version 'Y' of
    > StdCPP compiler. And then, if 'X' and 'Y' versions of CPP compiler are
    > not compatible, then we get into trouble. We have hit this several
    > times with different gcc versions. Just wondering, what is the best/
    > cleanest way to solve/get-around this problem?


    Have you surveyed your user population? Can you set up virtual Linuces with each
    of these versions?
    Phlip, May 31, 2009
    #2
    1. Advertising

  3. rabbits77 Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are thereclean ways to solve known problems there?

    wrote:
    > Hi
    >
    > I needed to build up a public API for an application at hand.
    >
    > The data I am modelling maps very well to object oriented design, so I
    > am little inclined towards a C++ public API (i.e. my deliverables
    > would be a <xyz>.hpp file which will have a bunch of pure virtual
    > functions forming the interface and a lib<xyz>.so which will basically
    > contain the implementation for those interfaces).

    Can you write your public API in the most general
    standards conforming way(no platform specific
    calls)? If so, great! Do so!
    You can be pretty much assured that it will work no
    matter whether users try it with Visual C++ or g++
    or whatever.
    Then as an added bonus add on other language APIs on
    top with SWIG. :)
    rabbits77, Jun 1, 2009
    #3
  4. Phlip Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are thereclean ways to solve known problems there?

    rabbits77 wrote:

    > Can you write your public API in the most general standards conforming
    > way(no platform specific calls)? If so, great! Do so!


    That answers the wrong question. The API has two interfaces, one
    programmer-facing and the other hardware-facing. The question was about keeping
    the upper layer clean and portable.

    Almost no program can do anything without platform specific calls - even tasks
    as mundane as file reconnaissance are platform-specific. The OP is advised to
    get into some full-featured portable platform, such as Qt or wxWindows, to get a
    kit of all of those functions, readily ported and supported to a wide variety of
    platforms. (Those platforms also come with nice GUI layers, which one can
    exploit or ignore.)
    Phlip, Jun 1, 2009
    #4
  5. Tony Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are there clean ways to solve known problems there?

    Without even reading the body or you post, I suggest you consider "C++ Guru"
    and expand your question to include the out of the box thinkers, for your
    question is a design one rather than a language-specific one, at least to
    some large degree, I think. When I think of "C++ Guru", I think of those
    heavily knowledgeable of the C++ standard, who indeed are valuable (if not
    temporary) walking/talking encyclonairies. Heavy knowledge in the C++
    monstrosity leaves less "ROM" (subjective to some degree, but not mostly to
    a high degree) for stuff outside of that narrow box (Ref, definition of
    specialization: one learns more and more about less and less until they know
    everything about nothing). Add that politics are more likely to be given
    (knowingly or unknowingly via paradigmical thought), rather than unbiased
    thought, and you have an answer that seemingly is good, but is just BS (at
    worst).
    Tony, Jun 1, 2009
    #5
  6. Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are thereclean ways to solve known problems there?

    On 1 June, 05:55, "Tony" <> wrote:

    > Without even reading the body or you post, I suggest you consider "C++ Guru"
    > and expand your question to include the out of the box thinkers, for your
    > question is a design one rather than a language-specific one, at least to
    > some large degree,


    this is about the sanest of Tony' recent posts. This probably *is* a
    design
    issue rather specifically a C++ problem. It certainly needs to deal
    with
    issues outside the C++ language.

    but then...

    > I think. When I think of  "C++ Guru", I think of those
    > heavily knowledgeable of the C++ standard, who indeed are valuable (if not
    > temporary) walking/talking encyclonairies.


    .... the great Word Salad came upon him and he was <snipped>


    --
    Nick Keighley
    , Jun 1, 2009
    #6
  7. Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are thereclean ways to solve known problems there?

    Posted to comp.programming in case they have any ideas on clean
    public interfaces

    On 31 May, 22:19, wrote:

    > I needed to build up a public API for an application at hand.
    >
    > The data I am modelling maps very well to object oriented design, so I
    > am little inclined towards a C++ public API (i.e. my deliverables
    > would be a <xyz>.hpp file which will have a bunch of pure virtual
    > functions forming the interface and a lib<xyz>.so which will basically
    > contain the implementation for those interfaces).


    as another poster pointed out your functions aren't virtual.
    Do your APIs contain classes?


    > But, I can think of 2 problems there:
    > 1) How do I guarantee that my shared library will work well with the
    > version of the C++ library/compiler my customer/user is having?
    > Issue in detail: I mean, I compile my shared library with version 'X'
    > of a Std CPP compiler and customer tries to use with version 'Y' of
    > StdCPP compiler. And then, if 'X' and 'Y' versions of CPP compiler are
    > not compatible, then we get into trouble. We have hit this several
    > times with different gcc versions. Just wondering, what is the best/
    > cleanest way to solve/get-around this problem?


    it's probably insoluable in *any* language. Might it be better
    to define an interface in terms of simple structures that are defined
    as streams of bytes. Then provide some sort of RPC interface.

    You might then look at ASN.1 or XML.

    You loose the tight coupling between your application and the client
    but gain the huge advantage of loosing the tight...


    <snip>

    --
    Nick Keighley
    , Jun 1, 2009
    #7
  8. Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are thereclean ways to solve known problems there?

    On May 31, 10:19 pm, wrote:

    > I needed to build up a public API for an application at hand.
    >
    > The data I am modelling maps very well to object oriented design, so I
    > am little inclined towards a C++ public API (i.e. my deliverables
    > would be a <xyz>.hpp file which will have a bunch of pure virtual
    > functions forming the interface and a lib<xyz>.so which will basically
    > contain the implementation for those interfaces).
    >
    > But, I can think of 2 problems there:
    > 1) How do I guarantee that my shared library will work well with the
    > version of the C++ library/compiler my customer/user is having?
    > Issue in detail: I mean, I compile my shared library with version 'X'
    > of a Std CPP compiler and customer tries to use with version 'Y' of
    > StdCPP compiler. And then, if 'X' and 'Y' versions of CPP compiler are
    > not compatible, then we get into trouble. We have hit this several
    > times with different gcc versions. Just wondering, what is the best/
    > cleanest way to solve/get-around this problem?


    If you ship a C++ interface, you will have to provide a different
    binary for every different version of OS and compiler your clients
    use. This is because C++ ABI differs across compilers and even
    compiler versions (e.g. gcc3 vs gcc4, sunCC vs. sunCC -
    library=stlport4).

    On the other hand, if you ship a C interface, you will only need to
    provide different binaries for each OS. This is because C ABI is
    stable and your clients can link against your C API using any compiler
    for that particular OS.

    Note, that you can do OO design in C. For example, a C++ intreface:

    struct Foo
    {
    int doSomething(int);
    };

    Would look like this in C:

    struct Foo; /* incomplete in the public API */
    Foo* fooCreate();
    void fooDestroy(Foo*);
    int fooDoSomething(Foo*, int);


    > 2) Sometimes it happens that you are working on a C++ based product
    > which already has millions of lines of code and then, one fine day a
    > requirement comes that a part of that chunk needs to be made accesible
    > to users through a shared library. Now, which you work towards
    > building that shared library, you may want to ensure that only symbols
    > that *should be* exported to users/customers, needs to be exported in
    > the shared library, all others un-wanted globals should not be
    > exported in the shared library to ensure we don't un-necessarily
    > pollute customer's namesapce with whole lot of our internal/global
    > symbols. (Note: Ideal solution for this issue, probably would be to
    > ensure that we should never pollute our implementation namespace at
    > all, in the first place, but as I said, you may not be the one who had
    > written all these code and it's a million lines code, and you don't
    > have the option/bugdet for re-arch/re-write!). For such a requriement,
    > if it was a C library we could typically use 'objcopy' in linux or -M
    > compiler option in Solaris, to make sure only a given set of symbols
    > (defined by us) are made global. But if it's a C++ library, I wonder
    > how to achieve this goal?


    By exposing a C interface, so that your .so only exports the functions
    of the public C API, all other symbols are made local or stripped.
    (Don't forget to statically prelink your .so with a C++ run-time, so
    that your C API .so does not have any unresolved C++ run-time
    symbols).

    --
    Max
    Maxim Yegorushkin, Jun 1, 2009
    #8
  9. cr88192 Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are there clean ways to solve known problems there?

    <> wrote in message
    news:...
    > Hi
    >
    > I needed to build up a public API for an application at hand.
    >
    > The data I am modelling maps very well to object oriented design, so I
    > am little inclined towards a C++ public API (i.e. my deliverables
    > would be a <xyz>.hpp file which will have a bunch of pure virtual
    > functions forming the interface and a lib<xyz>.so which will basically
    > contain the implementation for those interfaces).
    >


    <snip>

    >
    > Question: Is there a cleaner/better way to handle this?
    >
    > Thanks in advance for oyour time and help!
    >


    well, as a few others have said, and I am inclined to agree, my advice is
    this:
    make the external API be a C-based API.

    then, it does not so much matter if the library is written in C, C++, or
    some other language.
    similarly, it will not matter if the client is written in C, C++, or some
    other language (remember, not everyone uses C++, or is inclined to be bound
    to using C++ for sake of a library...).


    I will take it a little further, namely, the API should be an "abstract"
    API, which in this context basically means:
    no directly shared data structures (not as difficult, given it would likely
    be C++ classes and a C-based API internally, but just as a point of
    emphasis: it is rarely a good idea to have shared structures across API
    boundaries);
    instead, one can use handles, which are typically either integers or opaque
    pointers (often "typedef void *myHandleType;" or similar...);
    operations and mutations can still be performed, but typically this is via
    some collection of abstract wrapper functions;
    any data shared should be passed in buffers, and where ideally these buffers
    should be no more complex than that of flat arrays (int, float, ...);
    should complex data need to be passed, a personal recomendation is to use a
    textual, or some other "cannonical" (as in, an established format)
    serialization;
    ....

    the reasons for the above are subtle, but important:
    directly sharing data and structures between the client and the library is a
    good way to make a mess;
    in particular, it can tend to cause the client and the library to become
    interdependent, and may often lead to minor changes to one side breaking the
    other.

    after learning this one from experience a few times over, I had adopted
    this, arguably overly-strict seeming position (yes, shared data may seem to
    make the API more "friendly" or allow tighter coupling, but very often, this
    is more of an enemy than a friend...).

    as for the buffer rule:
    this is similar, and often it turns out this way in practice;
    the more complex the passed data is, the more likely it is to need to be
    changed later;
    textual serializations partly sidestep this rule, as for a given data
    complexity a textual format will almost invariably be drastically more
    "generic" than an equivalent binary format (it is the case, don't expect me
    to explain it, it relies on some esoteric properties...);
    a "cannonical" format may also be an option, where this is usually a common
    fileformat established for some specific use, for which it may make sense to
    pass in a buffer (examples: JPEG, PNG, COFF, ELF, ...).

    note (further justification of textual serialization):
    it may seem like such a serialization would contribute a good deal of
    overhead, however this has not been my experience in practice;
    it can be noted that, in most cases where it is necessary to send complex
    data, there is also typically a good deal of processing involved, which
    would by far dwarf any real (noticable) cost of serializing the text, and
    parsing it again;
    it can be further noted that, in some cases, specially-crafted text formats
    (and with specialized processing code), can match or exceed the raw
    performance than could have been achieved via an equivalent binary format
    (the key is that not all text needs to be "parsed", and infact, in many
    cases it is possible to make what is, essentially, an ASCII-based binary
    format...). similarly, although typically cryptic, there is an advantage
    that a person familiar with the serialization can directly "read" the data
    unaided (whereas a pure-binary format will almost invariably require a
    hex-dump), which is particularly helpful with debugging.

    granted though, this latter case is not to always be pursued, as it does not
    scale so well to larger-scale complexities (at which point it may impose
    similar problems to a plain binary format), however, often-times a good
    portion of an otherwise more "generic" textual serialization can make good
    use of individual components structured in this way (use with discretion,
    however...).

    note that I am not recommending that everything use XML or somesuch, as for
    most tasks, this would be highly overkill, rather, usually a specialized
    token-based format is sufficient.


    and so on...


    FWIW, I will add more:
    given C has a single massive shared toplevel, it makes sense to "prefix"
    function and type names with some prefix consistent to the library, and
    hopefully unlikely to clash with any other library.

    a personal style I use is:
    libprefixCamelCase(...);
    this style being (more or less) reserved for external API functions in my
    case.


    but, where internally I typically use:
    LIBNAME_SubSys_CamelCase(...);
    or just:
    LIBNAME_CamelCase(...); //this more for smaller, more single-purpose, libs

    similarly, in C++-based libraries, namespaces are a good option as well (for
    internal use).


    keeping this distinction may also better help one keep in mind what is
    internal, and what is intended to be part of the external API.

    I will also recommend that one actually put in effort and "design" the API,
    whereas personally I don't feel as strongly about design WRT the internal
    workings of a library (where, often, one may need to change and
    rework/redesign the internals maybe numerous times before one has them "just
    right", and so personally I would not recommend making the internals so much
    "set in stone", whereas the external API is something which should hopefully
    change sparingly, if at all...).

    or such...
    cr88192, Jun 1, 2009
    #9
  10. Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are thereclean ways to solve known problems there?

    On Jun 1, 2:41 am, (blargg) wrote:
    > wrote:
    > > I needed to build up a public API for an application at hand.

    >
    > > The data I am modelling maps very well to object oriented design, so I
    > > am little inclined towards a C++ public API (i.e. my deliverables
    > > would be a <xyz>.hpp file which will have a bunch of pure virtual
    > > functions forming the interface and a lib<xyz>.so which will basically
    > > contain the implementation for those interfaces).

    >
    > > But, I can think of 2 problems there:
    > > 1) How do I guarantee that my shared library will work well with the
    > > version of the C++ library/compiler my customer/user is having?
    > > Issue in detail: I mean, I compile my shared library with version 'X'
    > > of a Std CPP compiler and customer tries to use with version 'Y' of
    > > StdCPP compiler. And then, if 'X' and 'Y' versions of CPP compiler are
    > > not compatible, then we get into trouble. We have hit this several
    > > times with different gcc versions. Just wondering, what is the best/
    > > cleanest way to solve/get-around this problem?

    >
    > Write a C wrapper. If your interface were
    >
    >     class Interface {
    >     public:
    >         virtual int f( double );
    >     };
    >
    >     Interface* new_foo();
    >
    > you could write a C wrapper as
    >
    >     typedef struct Interface Interface;
    >
    >     Interface* xyz_new_foo( void );
    >     void xyz_delete( Interface* );
    >     int xyz_f( Interface*, double );
    >
    > and it would be accessible from many languages.


    This

    > If you then wanted C++
    > users to have a more convenient interface, you could provide a client-side
    > wrapper for the C interface. :)


    and this. Specifically, provide a small wrapper class in a header only
    that implements itself in terms of the C API, and give this header to
    clients. The class will be compiled by the client's compiler, and all
    calls to your library will go through a stable C API. You gain the
    stability of the C API and a nice C++ interface class.

    Note that it's not always convenient, reasonable or practical to do it
    this way, but many times it is.
    , Jun 2, 2009
    #10
  11. cr88192 Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are there clean ways to solve known problems there?

    "blargg" <> wrote in message
    news:-sjc.supernews.net...
    > Paavo Helde wrote:
    >> blargg wrote:
    >> > Write a C wrapper.

    >>
    >> I second to that. C++ has many advantages over C, but binary
    >> interoperability is not one of them. Use C++ interfaces only when both
    >> parties are under your control and you can recompile them easily
    >> together.

    >
    > Not just binary, but conceptual interoperability. Almost all languages
    > have some means of calling C functions, and perhaps even passing and
    > returning structures. Lots of useful libraries can be presented in this
    > simple vocabulary. The dividing line between those that work well with a
    > C interface and those that need a C++ one is probably between libraries
    > that mostly provide data processing functions (like compression, media
    > file decoding) and rich data structures (like the STL, or most of boost).



    yes, I will add something here:
    I have noticed a similar effect before (although, granted, C++ is not my
    primary development language), where many APIs seem best served by a clean
    (or, almost sterile) and opaque API; yet others consist almost purely of
    utility code, which need not have the same design.

    for example, the API design which would work well on, say, a physics engine,
    would not be the same as the one for, say, ones' geometric-math library
    (even if they may typically be used in close relation to each other...).

    so, yeah, the best design likely depends a lot on what the library does...



    then of course, we have some people who could be paraphrased as "you must
    all bow before the greatness of OO"...
    cr88192, Jun 3, 2009
    #11
  12. Jorgen Grahn Guest

    Re: C++ Gurus - Is C++ a good choice for public API(s)??? Are there clean ways to solve known problems there?

    On Sun, 31 May 2009 15:04:26 -0700, Phlip <> wrote:
    > wrote:
    >
    >> I needed to build up a public API for an application at hand.

    >
    > You cannot do any of this by guessing or planning. To create a public API, you
    > must write at least three projects, and port them to three different platforms
    > (linux, mac & pc) come to mind. Then you must configure your unit tests to run
    > simultaneously on each of the three platforms, each time you save your code. (I
    > have done this before, between Linux & PC, using Samba. Both platforms compiled
    > simultaneously into the same folders.)


    What you claim is provably false. What if it's a Windows-specific API?
    Also, there is still no law which forces programmers to have unit tests.

    Maybe what you mean is that it's hard to invent, implement and
    maintain APIs, because you need to predict the needs of the users, and
    then pretend to be the user when testing the API. That I would agree
    with, strongly.

    ....
    >> The data I am modelling maps very well to object oriented design, so I
    >> am little inclined towards a C++ public API (i.e. my deliverables
    >> would be a <xyz>.hpp file which will have a bunch of pure virtual
    >> functions forming the interface and a lib<xyz>.so which will basically
    >> contain the implementation for those interfaces).

    >
    > That's not what "pure virtual" means. It means the methods _don't_ have
    > implementations. If you go this route, you will simply need virtual methods.
    > However...
    >
    > Why do you think the project will need an OO design? The point of OO is to
    > abstract and vary virtual methods behind common interfaces. Have you written any
    > sample code showing the best places for the virtual methods? They might not be
    > what you expect.


    OO doesn't mean run-time polymorphism to everyone. Maybe he just means
    that an API with classes seems like a good fit. (IIRC, Stroustrup
    calls that an "object-based design".)

    But that doesn't explain why he wants things virtual. Just to make it
    clear: you do *not* need 'virtual' to distribute shared libraries, or
    to distribute them in binary form only.

    > You might be safer - if your client actually _needs_ all these platforms - by
    > writing a C-style API. The C++ communities widely support this technique,
    > because most platforms enforce compatibility standards among simple functions.


    Yeah, I vote for a C API too. They are widely understood, widely used,
    and all serious languages can interface to them. (By all means, write
    a C++ wrapper for it, too -- maybe the customer will use it, or maybe
    you'll find weaknesses in the C API while doing it.)

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Ph'nglui mglw'nafh Cthulhu
    \X/ snipabacken.se> R'lyeh wgah'nagl fhtagn!
    Jorgen Grahn, Jun 14, 2009
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Charles A. Lackman
    Replies:
    1
    Views:
    1,323
    smith
    Dec 8, 2004
  2. SpamProof
    Replies:
    0
    Views:
    530
    SpamProof
    Oct 21, 2003
  3. Mickey Segal
    Replies:
    0
    Views:
    855
    Mickey Segal
    Feb 2, 2004
  4. Replies:
    4
    Views:
    1,853
    Babu Kalakrishnan
    Oct 5, 2004
  5. sturlamolden
    Replies:
    0
    Views:
    435
    sturlamolden
    Sep 12, 2008
Loading...

Share This Page