CGO: Casting to another type

508 views
Skip to first unread message

OmarShariffDontLikeIt

unread,
Sep 4, 2011, 8:32:54 AM9/4/11
to golang-nuts
Hi everybody,

I'm still having problems with a CGO package I'm trying to write. I'm
attempting to write a simple package that provides access to libtidy,
the HTML Tidy library. The issue I have is that I get the following
error message (amongst others, but one at a time eh? :) )

main.go:33[_obj/main.cgo1.go:36]: cannot use input (type *_Ctype_char)
as type *_Ctypedef_tmbchar in function argument

Now, I'm also trying to learn how CGO works, so I understand that CGO
creates a bunch of additional files. I've located the file _obj/
main.cgo1.go which refers to the _Ctypedef_tmbchar type, and I
understand that C.CString creates a _Ctype_char from a Go string.
However, when I look at _obj/main.cgo1.go I can see this definition:

type _Ctypedef_tmbchar _Ctype_char

So, my rough theory of how Go casts, this suggests that I should be
able to cast _Ctype_char to _Ctypedef_tmbchar?
If so, I found that the following code doesn't work:

rc = C.tidyParseString( tdoc, _Ctypedef_tmbchar.(input) )

But I get the error message:

main.go:33[_obj/main.cgo1.go:36]: type _Ctypedef_tmbchar is not an
expression

So, I'm kinda stuck. Can someone point me in the right direction: what
have I missed here that enables me to cast _Ctype_char to the required
_Ctypedef_tmbchar type?

See code below:

package tidy

/*
#cgo CFLAGS: -I/usr/include
#cgo LDFLAGS: -ltidy -L/usr/local/lib/libtidy.a
#include <tidy.h>
#include <buffio.h>
#include <errno.h>
*/
import "C"
import (
"fmt"
"os"
"unsafe"
)

func Tidy(htmlSource string) (string, os.Error) {
input := C.CString(htmlSource)
defer C.free(unsafe.Pointer(input))

var output C.TidyBuffer
defer C.tidyBufFree( &output )

var errbuf C.TidyBuffer
defer C.tidyBufFree( &errbuf )

var rc C.int = -1
var ok C.Bool

var tdoc C.TidyDoc = C.tidyCreate() // Initialize "document"
defer C.tidyRelease( tdoc )

ok = C.tidyOptSetBool( tdoc, C.TidyXhtmlOut, C.yes ) // Convert to
XHTML

if ok == 1 {
rc = C.tidySetErrorBuffer( tdoc, &errbuf ) // Capture diagnostics
}

if rc >= 0 {
rc = C.tidyParseString( tdoc, input ) // Parse the input
}

if rc >= 0 {
rc = C.tidyCleanAndRepair( tdoc ) // Tidy it up!
}

if rc >= 0 {
rc = C.tidyRunDiagnostics( tdoc ) // Kvetch
}

if rc > 1 { // If error, force output.
if C.tidyOptSetBool(tdoc, C.TidyForceOutput, C.yes) == -1 {
rc = -1
}
}

if rc >= 0 {
rc = C.tidySaveBuffer( tdoc, &output ) // Pretty Print
}

if rc >= 0 {
if rc > 0 {
return C.GoString(output.bp), os.NewError(C.GoString(errbuf.bp))
}
return C.GoString(output.bp), nil
} else {
return "", os.NewSyscallError(fmt.Sprintf( "A severe error (%d)
occurred.\n", rc ), rc)
}
}



Thanks again,
Ben

Evan Shaw

unread,
Sep 5, 2011, 12:24:39 AM9/5/11
to OmarShariffDontLikeIt, golang-nuts
On Mon, Sep 5, 2011 at 12:32 AM, OmarShariffDontLikeIt
<omarsharif...@gmail.com> wrote:
> rc = C.tidyParseString( tdoc, _Ctypedef_tmbchar.(input) )

I think you want:

rc = C.tidyParseString(tdoc, _Ctypedef_tmbchar(input))

In other words, remove the dot ('.').

- Evan

OmarShariffDontLikeIt

unread,
Sep 5, 2011, 2:49:38 AM9/5/11
to golang-nuts

On Sep 5, 5:24 am, Evan Shaw <eds...@gmail.com> wrote:
> On Mon, Sep 5, 2011 at 12:32 AM, OmarShariffDontLikeIt
>
> <omarshariffdontlik...@gmail.com> wrote:
> > rc = C.tidyParseString( tdoc, _Ctypedef_tmbchar.(input) )
>
> I think you want:
>
> rc = C.tidyParseString(tdoc, _Ctypedef_tmbchar(input))
>
> In other words, remove the dot ('.').
>
> - Evan

Gah! What a stupid mistake! Thanks for pointing it out to me :) Below
is the amended, correctly compiling code:
in := _Ctypedef_tmbchar(*input)
rc = C.tidyParseString( tdoc, &in ) // Parse the input
}

if rc >= 0 {
rc = C.tidyCleanAndRepair( tdoc ) // Tidy it up!
}

if rc >= 0 {
rc = C.tidyRunDiagnostics( tdoc ) // Kvetch
}

if rc > 1 { // If error, force output.
if C.tidyOptSetBool(tdoc, C.TidyForceOutput, C.yes) == 0 {
rc = -1
}
}

if rc >= 0 {
rc = C.tidySaveBuffer( tdoc, &output ) // Pretty Print
}

if rc >= 0 {
out := _Ctype_char(*output.bp)
if rc > 0 {
err := _Ctype_char(*errbuf.bp)
return C.GoString(&out), os.NewError(C.GoString(&err))
}
return C.GoString(&out), nil
}
return "", os.NewSyscallError(fmt.Sprintf( "A severe error (%d)
occurred.\n", int(rc) ), int(rc))
}
Reply all
Reply to author
Forward
0 new messages