I have this IL code from Expert .NET 2.0 IL Assembler by Serge Lidin:
This is in a file called CilTest.il:
//----------- Program header
.assembly extern mscorlib { auto }
.assembly OddOrEven { }
.module OddOrEven.exe
//----------- Class declaration
.namespace Odd.or {
.class public auto ansi Even extends [mscorlib]System.Object {
//----------- Field declaration
.field public static int32 val
//----------- Method declaration
.method public static void check( ) cil managed {
.entrypoint
.locals init (int32 Retval)
AskForNumber:
ldstr "Enter a number"
call void [mscorlib]System.Console::WriteLine (string)
call string [mscorlib]System.Console::ReadLine ()
ldsflda valuetype CharArray8 Format
ldsflda int32 Odd.or.Even::val
call vararg int32 sscanf(string,int8*,...,int32*)
stloc Retval
ldloc Retval
brfalse Error
ldsfld int32 Odd.or.Even::val
ldc.i4 1
and
brfalse ItsEven
ldstr "odd!"
br PrintAndReturn
ItsEven:
ldstr "even!"
br PrintAndReturn
Error:
ldstr "How rude!"
PrintAndReturn:
call void [mscorlib]System.Console::WriteLine (string)
ldloc Retval
brtrue AskForNumber
ret
} // End of method
} // End of class
} // End of namespace
//----------- Global items
.field public static valuetype CharArray8 Format at FormatData
//----------- Data declaration
.data FormatData = bytearray(25 64 00 00 00 00 00 00) // % d . . . . . .
//----------- Value type as placeholder
.class public explicit CharArray8
extends [mscorlib]System.ValueType { .size 8 }
//----------- Calling unmanaged code
.method public static pinvokeimpl("msvcrt.dll" cdecl)
vararg int32 sscanf(string,int8*) cil managed { }
The following file is in the same folder and called CilTest.ilproj:
<Project Sdk="Microsoft.Net.Sdk.il/7.0.0">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
</Project>
I'm compiling the code using:
dotnet build -r win-x64 --self-contained -c release
When I run the code, I get this error:
It seems as though the call to sscanf
returns 0 successful formatted strings:
call vararg int32 sscanf(string,int8*,...,int32*)
Why is sscanf()
not working?
Is there a way to debug the code so I can see why sscanf()
is not working?
Add keyword preservesig after cil managed, like this:
//----------- Calling unmanaged code
.method public static pinvokeimpl("msvcrt.dll" cdecl)
vararg int32 sscanf(string,int8*) cil managed preservesig { }
In .NET implementations later than 2.0 this keyword is required to indicate that the return value of the P/Invoke method has to be preserved.