I've disassmebled the following C++/CLI code in ildasm:
Managed(char * const a)
{
}
and the disassembled IL looks like this:
.method public hidebysig specialname rtspecialname
instance void .ctor(int8 modopt([mscorlib]System.Runtime.CompilerServices.IsSignUnspecifiedByte)* modopt([mscorlib]System.Runtime.CompilerServices.IsConst) modopt([mscorlib]System.Runtime.CompilerServices.IsConst) a) cil managed
Removing some insignificant parts:
.method public hidebysig specialname rtspecialname
instance void .ctor(int8* modopt(IsConst) modopt(IsConst) a) cil managed
So while there is only one const in the original code, it is emitted twice in the IL. Why is that so?
Related
For some reason I can't work out yet, my agent doesn't intercept java LinkageError instances.
Agent code:
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.matcher.ElementMatchers;
import java.lang.instrument.Instrumentation;
public class MyAgent {
public static void premain(String arguments, Instrumentation instrumentation) {
new AgentBuilder.Default()
.type(ElementMatchers.isSubTypeOf(LinkageError.class))
.transform((builder, type, classLoader, module) ->
builder.constructor(ElementMatchers.isDefaultConstructor())
.intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.to(MyInterceptor.class)))
).installOn(instrumentation);
}
}
Interceptor code:
public class MyInterceptor {
#RuntimeType
public static void intercept(#Origin Constructor<?> constructor) throws Exception {
System.out.println("Intercepted: " + constructor.getName());
}
}
Test code:
public static void main(String[] args) {
new NoClassDefFoundError("should be intercepted!!!").toString();
new Foo("oh").toString();
}
What is puzzling is that replacing ElementMatchers.isSubTypeOf(LinkageError.class) with ElementMatchers.nameContains("Foo") gives the expected result and Foo constructor is intercepted.
The NoClassDefFoundError is loaded by the bootstrap loader. It willnot be able to see your interceptor class which is why it is never triggered.
Try using the Advice class (as a visitor) to add bytecode to matched classes which should resolve this problem.
I'm working on a custom Lint check and can't get all the method calls I need.
What I need: access to every add() call in lines like this:
Builder.from(arg)
.add(arg1, arg2)
.add(arg1, arg2)
.add(arg1, arg2);
What I get: visitMethod is not called at all. In such lines it's only called for 'from()'.
Detector code sample:
public class ExampleDetector extends Detector implements Detector.JavaPsiScanner {
#Override
public List<String> getApplicableMethodNames() {
return Collections.singletonList("add");
}
#Override
public void visitMethod(JavaContext context, #Nullable JavaElementVisitor visitor,
#NonNull PsiMethodCallExpression call, #NonNull PsiMethod method) {
...
}
....
}
How can I solve it? Why is it not visited at all?
Let have these overloaded methods in a class:
class Test{
public void func1(int X , String s) {
// do something
}
public void func1(int X) {
// do something
}
public void func1(int X , int Y) {
// do something
}
what happen (what does the compiler do) when func1(2,3) from another class is called:
the compiler finds directly the thired version of func1 in class Test like calling non-overloaded methods or
like if-else statements, the entire overloaded methods with name func1 are tested to find which of them has the same set of arguments as func(2,3)
I searched in some documentations but couldn't find the answer.
I'm interested in binding to iOS Foundation functions as seen in the iOS documentation but there aren't any handles or instances to send a message to invoke them. How would I do this with MonoTouch? I would think that it would involve something within the MonoTouch.ObjCRuntime namespace.
All of MonoTouch's NS* objects implement the MonoTouch.ObjCRuntime.INativeObject interface which has a property getter called "Handle". This accessor is public on NSObject and all subclasses.
Edit: code to bind NSSetUncaughtExceptionHandler() will be something like this:
public delegate void NSUncaughtExceptionHandler (IntPtr exception);
[DllImport ("/System/Library/Frameworks/Foundation.framework/Foundation")]
extern static void NSSetUncaughtExceptionHandler (IntPtr handler);
Then you could use it like this:
static void MyUncaughtExceptionHandler (IntPtr exception)
{
// Got an exception...
}
static void Main (string[] args)
{
NSSetMyUncaughtExceptionHandler (Marshal.GetFunctionPointerForDelegate(
new NSUncaughtExceptionHandler(
MyUncaughtExceptionHandler
)
);
}
I have the following interfaces that are part of an existing project. I'd like to make it possible to call the Store(..) function with dynamic objects. But I don't want to change the Interface hierarchy (if at all possible).
public interface IActualInterface
{
void Store(object entity);
}
public interface IExtendedInterface : IActualInterface
{
//Interface items not important
}
public class Test : IExtendedInterface
{
public void Store(object entity)
{
Console.WriteLine("Storing: " + entity.ToString());
}
}
and the following code:
IExtendedInterface extendedInterfaceTest = new Test();
IActualInterface actualInterfaceTest = new Test();
Test directTest = new Test();
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
employee.Phones = new ExpandoObject();
employee.Phones.Home = "0111 123123";
employee.Phones.Office = "027 321123";
employee.Tags = new List<dynamic>() { 123.4D, 99.54D };
try
{
extendedInterfaceTest .Store(employee);
}
catch (RuntimeBinderException rbEx)
{
Console.WriteLine(rbEx.Message);
}
//Casting as (object) works okay as it's not resolved at runtime
extendedInterfaceTest.Store((object)employee);
//this works because IActualInterface implements 'Store'
actualInterfaceTest.Store(employee);
//this also works okay (directTest : IProxyTest)
directTest.Store(employee);
When I call extendedInterfaceTest.Store(employee), it raises a runtime binder exception. Why does the interface type make a difference when it's the same underlying type? I can call it on IActualInterface and Type, but not IExtendedInterface?
I understand that when calling a function with a dynamic parameter, the resolution happens at runtime, but why the different behaviours?
What you need to remember is that dynamic resolution basically does the same process as static resolution, but at runtime. Anything that couldn't be resolved by the CLR won't be resolved by the DLR.
Let's take this small program, inspired by yours, and that doesn't use dynamic at all:
namespace ConsoleApplication38 {
public interface IActualInterface {
void Store(object entity);
}
public interface IExtendedInterface : IActualInterface {
}
public class TestInterface : IExtendedInterface {
public void Store(object entity) {
}
}
public abstract class ActualClass {
public abstract void Store(object entity);
}
public abstract class ExtendedClass : ActualClass {
}
public class TestClass : ExtendedClass {
public override void Store(object entity) {
}
}
class Program {
static void TestInterfaces() {
IActualInterface actualTest = new TestInterface();
IExtendedInterface extendedTest = new TestInterface();
TestInterface directTest = new TestInterface();
actualTest.Store(null);
extendedTest.Store(null);
directTest.Store(null);
}
static void TestClasses() {
ActualClass actualTest = new TestClass();
ExtendedClass extendedTest = new TestClass();
TestClass directTest = new TestClass();
actualTest.Store(null);
extendedTest.Store(null);
directTest.Store(null);
}
static void Main(string[] args) {
TestInterfaces();
TestClasses();
}
}
}
Everything compiles fine. But what did the compiler really generate? Let's see using ILdasm.
For the interfaces:
// actualTest.Store
IL_0015: callvirt instance void ConsoleApplication38.IActualInterface::Store(object)
// extendedTest.Store
IL_001d: callvirt instance void ConsoleApplication38.IActualInterface::Store(object)
// directTest.Store
IL_0025: callvirt instance void ConsoleApplication38.TestInterface::Store(object)
We can see here that the C# compiler always generates calls for the interface or class where the method is defined. IActualInterface has a method slot for Store so it's used for actualTest.Store. IExtendedInterface doesn't, so IActualInterface is used for the call. TestInterface defines a new method Store, using the newslot IL modifier, effectively assigning a new slot in the vtable for that method, so it's directly used since directTest is of type TestInterface.
For the classes:
// actualTest.Store
IL_0015: callvirt instance void ConsoleApplication38.ActualClass::Store(object)
// extendedTest.Store
IL_001d: callvirt instance void ConsoleApplication38.ActualClass::Store(object)
// directTest.Store
IL_0025: callvirt instance void ConsoleApplication38.ActualClass::Store(object)
For the 3 different types, the same call is generated because the method slot is defined on ActualClass.
Let's now see what we get if we write the IL ourselves, using the type we want rather than letting the C# compiler choosing it for us. I've modified the IL to look like this:
For interfaces:
// actualTest.Store
IL_0015: callvirt instance void ConsoleApplication38.IActualInterface::Store(object)
// extendedTest.Store
IL_001d: callvirt instance void ConsoleApplication38.IExtendedInterface::Store(object)
// directTest.Store
IL_0025: callvirt instance void ConsoleApplication38.TestInterface::Store(object)
For classes:
// actualTest.Store
IL_0015: callvirt instance void ConsoleApplication38.ActualClass::Store(object)
// extendedTest.Store
IL_001d: callvirt instance void ConsoleApplication38.ExtendedClass::Store(object)
// directTest.Store
IL_0025: callvirt instance void ConsoleApplication38.TestClass::Store(object)
The program compiles fine with ILasm. However it fails to pass peverify and crashes at runtime with the following error:
Unhandled Exception:
System.MissingMethodException: Method
not found: 'Void
ConsoleApplication38.IExtendedInterface.Store(System.Object)'.
at
ConsoleApplication38.Program.TestInterfaces()
at
ConsoleApplication38.Program.Main(String[]
args)
If you remove this invalid call, the derived classes calls work fine without any error. The CLR is able to resolve the base method from the derived type call. However interfaces have no true representation in runtime, and the CLR isn't able to resolve the method call from the extended interface.
In theory, the C# compiler could emit the call directly to the correct class specified in the runtime. It would avoid problems about middle classes calls as seen on Eric Lippert's blog. However as demonstrated, this is not possible for interfaces.
Let's get back to the DLR. It resolves the method exactly the same way as the CLR. We've seen that IExtendedInterface.Store couldn't be resolved by the CLR. The DLR cannot either! This is totally hidden by the fact that the C# compiler will emit the right call, so always be careful when using dynamic unless you perfectly know how it works in the CLR.