Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gopy: only one function signature arg allowed #332

Open
mauserzjeh opened this issue Jul 10, 2023 · 1 comment
Open

gopy: only one function signature arg allowed #332

mauserzjeh opened this issue Jul 10, 2023 · 1 comment

Comments

@mauserzjeh
Copy link

First of all, my aim is to be able to load certain assets in memory with multiple goroutines for speed/performance and once an asset is loaded into memory I would like to call a callback function that would be passed from python.

i.e:

  • Have a golang function that loads assets/files into memory
  • This function is built into the python module, thus I can call it from python and additionally pass callback functions to it
  • Assets are loaded in multiple goroutines
  • Every time an asset is loaded, call a callback function, which was passed to the import function

What am I doing wrong?

I get the following error when trying to build my package:

gopy: only one function signature arg allowed

$ ./build_importer.sh
go build -v importer

--- Processing package: importer ---
ignoring python incompatible method: importer.func (*importer.Importer).ImportIBSP(assetPath string, filePath string, poolSize uint, callbackIbsp func(importer.LoadedIBSP), callbackMaterial func(importer.LoadedMaterial), callbackXmodel func(importer.LoadedModel)) error: func(assetPath string, filePath string, poolSize uint, callbackIbsp func(importer.LoadedIBSP), callbackMaterial func(importer.LoadedMaterial), callbackXmodel func(importer.LoadedModel)) error: gopy: only one function signature arg allowed: func(assetPath string, filePath string, poolSize uint, callbackIbsp func(importer.LoadedIBSP), callbackMaterial func(importer.LoadedMaterial), callbackXmodel func(importer.LoadedModel)) error
no LibDir -- copy from IncDir: C:/Users/soma/AppData/Local/Programs/Python/Python311/Include
no LibPy -- set to: python311
no LibDir -- copy from IncDir: C:/Users/soma/AppData/Local/Programs/Python/Python311/Include
no LibPy -- set to: python311

--- building package ---
gopy.exe build -output=importer -vm=python importer
goimports -w importer.go
no LibDir -- copy from IncDir: C:/Users/soma/AppData/Local/Programs/Python/Python311/Include
no LibPy -- set to: python311
go build -mod=mod -buildmode=c-shared -o importer_go.pyd .
C:\Users\soma\AppData\Local\Programs\Python\Python311\python.exe build.py
Doing windows sed hack to fix declspec for PyInit
CGO_CFLAGS=-IC:/Users/soma/AppData/Local/Programs/Python/Python311/Include -fPIC -Ofast
CGO_LDFLAGS=-LC:/Users/soma/AppData/Local/Programs/Python/Python311/Include -lpython311
go build -mod=mod -buildmode=c-shared -o _importer.cp311-win_amd64.pyd .

this is the part of the code the error talks about:

// ImportBSP
func (imp *Importer) ImportIBSP(assetPath, filePath string, poolSize uint, callbackIbsp func(LoadedIBSP), callbackMaterial func(LoadedMaterial), callbackXmodel func(LoadedModel)) error {
	ibsp := assets.IBSP{}
	err := ibsp.Load(filePath)
	if err != nil {
		return errorLogAndReturn(err)
	}

	wp := newWorkerPool(poolSize)

	wg := sync.WaitGroup{}
	for _, mat := range ibsp.Materials {
		wg.Add(1)

		wp.addTask(func() {
			defer wg.Done()

			version := assets.VERSION_COD1
			if ibsp.Header.Version == assets.IBSP_VER_v4 {
				version = assets.VERSION_COD2
			}
			loadedMaterial, err := imp.loadMaterial(assetPath, mat.GetName(), version)
			if err != nil {
				errorLog(err)
				return
			}
                        
                        // python callback function
			callbackMaterial(loadedMaterial) // <--
		})

	}

	wg.Wait()

        // python callback function
	callbackIbsp(LoadedIBSP{
		IBSP: ibsp,
	}) // <--

	for _, ent := range ibsp.Entities {
		wg.Add(1)

		wp.addTask(func() {
			defer wg.Done()

			xmodelFilePath := path.Join(assetPath, assets.ASSETPATH_XMODEL, ent.Name)
			loadedModel, err := imp.ImportXModel(assetPath, xmodelFilePath)
			if err != nil {
				errorLog(err)
				return
			}

			loadedModel.Angles = ent.Angles
			loadedModel.Origin = ent.Origin
			loadedModel.Scale = ent.Scale
                        
                        // python callback function
			callbackXmodel(loadedModel) // <--
		})
	}

	wg.Wait()

	wp.stop()
	return nil
}

// ImportXModel
func (imp *Importer) ImportXModel(assetPath, filePath string) (LoadedModel, error) {
	xmodel := assets.XModel{}
	err := xmodel.Load(filePath)
	if err != nil {
		return LoadedModel{}, errorLogAndReturn(err)
	}

	lod0 := xmodel.Lods[0]
	xmodelPartFilePath := path.Join(assetPath, assets.ASSETPATH_XMODELPARTS, lod0.Name)
	xmodelPart := &assets.XModelPart{}
	err = xmodelPart.Load(xmodelPartFilePath)
	if err != nil {
		errorLog(err)
		xmodelPart = nil
	}

	xmodelSurfFilePath := path.Join(assetPath, assets.ASSETPATH_XMODELSURFS, lod0.Name)
	xmodelSurf := assets.XModelSurf{}
	err = xmodelSurf.Load(xmodelSurfFilePath, xmodelPart)
	if err != nil {
		return LoadedModel{}, errorLogAndReturn(err)
	}

	loadedMaterials := []LoadedMaterial{}
	if xmodel.Version == assets.VERSION_COD2 || xmodel.Version == assets.VERSION_COD4 {
		for _, mat := range lod0.Materials {
			loadedMaterial, err := imp.loadMaterial(assetPath, mat, int(xmodel.Version))
			if err != nil {
				errorLog(err)
				continue
			}

			loadedMaterials = append(loadedMaterials, loadedMaterial)
		}
	}

	loadedModel := LoadedModel{
		XModel:     xmodel,
		XModelSurf: xmodelSurf,
		Materials:  loadedMaterials,
		Angles:     assets.Vec3{},
		Origin:     assets.Vec3{},
		Scale: assets.Vec3{
			X: 1,
			Y: 1,
			Z: 1,
		},
	}

	if xmodelPart != nil {
		loadedModel.XModelPart = *xmodelPart
	}

	return loadedModel, nil
}

// loadMaterial
func (imp *Importer) loadMaterial(assetPath, materialName string, version int) (LoadedMaterial, error) {
	materialFilePath := path.Join(assetPath, assets.ASSETPATH_MATERIALS, materialName)
	material := assets.Material{}
	err := material.Load(materialFilePath, version)
	if err != nil {
		return LoadedMaterial{}, errorLogAndReturn(err)
	}

	loadedTextures := map[string]assets.IWI{}
	for _, tex := range material.Textures {
		if _, ok := loadedTextures[tex.Name]; ok {
			continue
		}

		textFilePath := path.Join(assetPath, assets.ASSETPATH_TEXTURES, tex.Name)
		texture := assets.IWI{}
		err := texture.Load(textFilePath)
		if err != nil {
			errorLog(err)
			continue
		}

		loadedTextures[tex.Name] = texture
	}

	return LoadedMaterial{
		Material: material,
		Textures: loadedTextures,
	}, nil
}
@mauserzjeh
Copy link
Author

If I only pass one callback function it doesn't throw the error. How could I solve this problem when I need to call multiple callback functions, depending on the type of asset loaded?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant