| // Copyright 2012 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | //go:build !windows && !static && (!darwin || (!internal_pie && !arm64)) | 
 | // +build !windows | 
 | // +build !static | 
 | // +build !darwin !internal_pie,!arm64 | 
 |  | 
 | // Excluded in darwin internal linking PIE mode, as dynamic export is not | 
 | // supported. | 
 | // Excluded in internal linking mode on darwin/arm64, as it is always PIE. | 
 |  | 
 | package cgotest | 
 |  | 
 | /* | 
 | #include <stdint.h> | 
 | #include <dlfcn.h> | 
 | #cgo linux LDFLAGS: -ldl | 
 |  | 
 | extern uintptr_t dlopen4029(char*, int); | 
 | extern uintptr_t dlsym4029(uintptr_t, char*); | 
 | extern int dlclose4029(uintptr_t); | 
 |  | 
 | extern void call4029(uintptr_t arg); | 
 | */ | 
 | import "C" | 
 |  | 
 | import ( | 
 | 	"testing" | 
 | ) | 
 |  | 
 | var callbacks int | 
 |  | 
 | //export IMPIsOpaque | 
 | func IMPIsOpaque() { | 
 | 	callbacks++ | 
 | } | 
 |  | 
 | //export IMPInitWithFrame | 
 | func IMPInitWithFrame() { | 
 | 	callbacks++ | 
 | } | 
 |  | 
 | //export IMPDrawRect | 
 | func IMPDrawRect() { | 
 | 	callbacks++ | 
 | } | 
 |  | 
 | //export IMPWindowResize | 
 | func IMPWindowResize() { | 
 | 	callbacks++ | 
 | } | 
 |  | 
 | func test4029(t *testing.T) { | 
 | 	loadThySelf(t, "IMPWindowResize") | 
 | 	loadThySelf(t, "IMPDrawRect") | 
 | 	loadThySelf(t, "IMPInitWithFrame") | 
 | 	loadThySelf(t, "IMPIsOpaque") | 
 | 	if callbacks != 4 { | 
 | 		t.Errorf("got %d callbacks, expected 4", callbacks) | 
 | 	} | 
 | } | 
 |  | 
 | func loadThySelf(t *testing.T, symbol string) { | 
 | 	this_process := C.dlopen4029(nil, C.RTLD_NOW) | 
 | 	if this_process == 0 { | 
 | 		t.Error("dlopen:", C.GoString(C.dlerror())) | 
 | 		return | 
 | 	} | 
 | 	defer C.dlclose4029(this_process) | 
 |  | 
 | 	symbol_address := C.dlsym4029(this_process, C.CString(symbol)) | 
 | 	if symbol_address == 0 { | 
 | 		t.Error("dlsym:", C.GoString(C.dlerror())) | 
 | 		return | 
 | 	} | 
 | 	t.Log(symbol, symbol_address) | 
 | 	C.call4029(symbol_address) | 
 | } |