DeanoCalver

Sorry this is likely to be a bit confusing, as its fairly complex...

I have a Managed C++ Library (called Lua2ILContentImport) with a custom content pipeline in it, its has to be Managed C++ because it embed a fair chunk of old C code in it (Lua 5.0 for the curious), I also have a C# library (called Lua2IL) that runs on PC and 360 (a define removed some Emit calls on the 360, the rest is identical).
Lua2ILContentImport reference Lua2IL with the define defined so that a Lua byte code to CLR IL system is enabled using Reflection.Emit.

Now the product of the content pipeline is an assembly full of lovely IL that originally were Lua scripts. For testing I also have a tiny console driver that manually calls the content pipeline classes to make it easier for me to debug and test.
The test driver (wrapped in a main of course called Lua2ILC) is so trivial I can stick it here.
Lua2ILContentImport^ ci = gcnew Lua2ILContentImport();
Lua2ILProcessor^ processor = gcnew Lua2ILProcessor();
Lua2ILIntermediate^ im = ci->Import( args[0], nullptr);
if( im != nullptr )
{
processor->Process( im, nullptr );
}

Run it and out pops my assembly on disk, perfect...

So now try hooking the classes up to the content pipeline, all goes well, add it to Game Studio and it shows up there first time, and starts processing my lua file (i'm using a sample class called sieve.lua in all cases) but then the content pipeline throws an exception.

Error 1 Building content threw COMException: Record not found on lookup. (Exception from HRESULT: 0x80131130)
at System.Reflection.Module.InternalGetTypeToken(String strFullName, Module refedModule, String strRefedModuleFileName, Int32 tkResolution)
at System.Reflection.Emit.ModuleBuilder.GetTypeRefNested(Type type, Module refedModule, String strRefedModuleFileName)
at System.Reflection.Emit.ModuleBuilder.GetTypeTokenNoLock(Type type)
at System.Reflection.Emit.ModuleBuilder.GetTypeToken(Type type)
at System.Reflection.Emit.ModuleBuilder.InternalGetConstructorToken(ConstructorInfo con, Boolean usingRef)
at System.Reflection.Emit.ModuleBuilder.GetConstructorToken(ConstructorInfo con)
at System.Reflection.Emit.ILGenerator.GetMethodToken(MethodBase method, Type[] optionalParameterTypes)
at System.Reflection.Emit.ILGenerator.Emit(OpCode opcode, ConstructorInfo con)

I've truncated it down to the relevant bit. Essentially the IL.Emit is dying trying to lookup a "LuaReference" type (which is contained in the Lua2IL)... It looks like, when referenced by the content pipeline the type information that Reflection has is somehow different from using a console CLR exe

I've tried adding both Lua2ILContentImport AND Lua2IL to the content pipeline dialog on GSE in case it was some kind of reference thing but to no avail.

The same file processed using the driver stub above works, yet running inside GSE via the content pipeline dies with that hideous to debug Reflection problem...
I'm sure I'm running into some evil assembly stuff I don't know about, but for the life of me can't figure out what's different and most importantly how to fix it.

Any help or ideas would be good,

Thanks,
Deano


Re: XNA Game Studio Express Content Pipeline Type Environment Odditiy

Shawn Hargreaves - MSFT

Wow. That's an extremely odd error - I have absolutely no idea what could be causing this!

Sorry I can't be more help...





Re: XNA Game Studio Express Content Pipeline Type Environment Odditiy

Bjoern Graf

Without seeing some relevant code I can only give some generic tips on content processor (CP) debugging and other random thoughts - I have not used emit in a CP yet, but relection (with explicit assembly loading, though).

  • To test a CP, a command prompt window with a simple test project which contains the test content file and msbuild /t:Rebuild is much nicer/faster than using GSE and gives you a bit more text about what's going on
  • context.Logger.LogMessage is a nice tool to trace the flow inside your CP, especially when you are too lazy to attach a debugger; Yay to printf debugging... :)
  • TypeConverterAttributes seem to require a string instead of the type (e.g. [TypeConverter("Foo.Bar.MooConverter")] instead of [TypeConverter(typeof(MooConverter))]) to be used by reflection/inside a CP; this might be special to my usage only, though

Also, does the Lua2ILContentImport assembly reference the Lua2IL one





Re: XNA Game Studio Express Content Pipeline Type Environment Odditiy

Shawn Hargreaves - MSFT

Bjoern Graf wrote:
  • To test a CP, a command prompt window with a simple test project which contains the test content file and msbuild /t:Rebuild is much nicer/faster than using GSE and gives you a bit more text about what's going on


You can also turn on that more verbose build output inside C# Express. Go to Tools / Options, check "Show all settings", open up the Projects and Solutions / Build and Run tab, and change the MSBuild project build output verbosity from Minimal to Normal.





Re: XNA Game Studio Express Content Pipeline Type Environment Odditiy

DeanoCalver

Thanks for everybody help, I thankfully have managed to get it working (having learning ALOT more than I ever wanted to know about how .NET handles code assembly).

For the curious, its ended up being nothing to do with the content pipeline, but to do with the way AssemblyBuilder handles paths (I managed to get it happening with the CLI driver by using relative path). The original text parser to Lua bytecode compiler emdeded the source filename in (i.e. ..\sieve.lua) this then got passed via the bytecode to IL converter through to AssemblyBuilder which really doesn't like paths at all (there only one place you can have any kind of paths and thats DefineDynamicAssembly).
For some reason cos of how the path was getting through to AssemblyBuilder rather than getting a proper exception, all I got was the weird COMException.

Thanks for all the help,
Deano