JoshClose / CsvHelper

Library to help reading and writing CSV files
http://joshclose.github.io/CsvHelper/
Other
4.75k stars 1.06k forks source link

CsvReader does not work in Unity 2018.3.8f Android platform , il2cpp environments. #1304

Closed ghfhgh67 closed 4 years ago

ghfhgh67 commented 5 years ago

Hi.

Unity2018.3.8f build in il2cpp in Android platform environment after When assigning CsvReader, NullReferenceException occurs.

The CsvReader works fine on the editor, but build it in il2cpp and run it in the Android environment, it will cause the problem, but build it in mono instead of il2cpp, It does not occur.

JoshClose commented 5 years ago

What is il2cpp? Which version of CsvHelper are you using. net45 or netstandard2.0?

ghfhgh67 commented 5 years ago

What is il2cpp? Which version of CsvHelper are you using. net45 or netstandard2.0?

Sorry for the delay in my replying. il2cpp is a feature in Unity that converts C # code converted to IL code into C ++.   A detailed description is attached to the link.

https://blogs.unity3d.com/2015/05/06/an-introduction-to-ilcpp-internals/

  In addition, the version of CsvHelper uses the latest version 12.1.2, and the same symptom occurred when the test was performed with the 7.1.1 version which has the highest number of downloads.   .net is not a standard but .net 4.x for Unity.

ghfhgh67 commented 5 years ago

What is il2cpp? Which version of CsvHelper are you using. net45 or netstandard2.0?

Sorry for the delay in my replying. il2cpp is a feature in Unity that converts C # code converted to IL code into C ++.   A detailed description is attached to the link.

https://blogs.unity3d.com/2015/05/06/an-introduction-to-ilcpp-internals/

  In addition, the version of CsvHelper uses the latest version 12.1.2, and the same symptom occurred when the test was performed with the 7.1.1 version which has the highest number of downloads.   .net is not a standard but .net 4.x for Unity.

After further checking, It looks like the problem is in the ReflectionHelper.CreateInstanceDelegate function.

  In that function compiled = Expression.Lambda (constructor, argumentExpressions) .Compile (); Will result in null. The reason is, In the il2cpp environment, it seems like a restriction on the use of linq.

  This problem is currently being fixed by Unity Technology. https://forum.unity.com/threads/are-c-expression-trees-or-ilgenerator-allowed-on-ios.489498/#post-3665089

JoshClose commented 5 years ago

You might be able to create your own ObjectResolver implementation that uses Activator.CreateInstance instead.

Try putting this code before you create the CsvReader instance and see if that works.

ObjectResolver.Current = new ObjectResolver(type => true, Activator.CreateInstance);
ghfhgh67 commented 5 years ago

You might be able to create your own ObjectResolver implementation that uses Activator.CreateInstance instead.

Try putting this code before you create the CsvReader instance and see if that works.

ObjectResolver.Current = new ObjectResolver(type => true, Activator.CreateInstance);

Thank you for answer. I've tried putting the code and running it, but I get this error.

05-15 12:12:38.012 30243-30292/? E/Unity: ExecutionEngineException: Attempting to call method 'CsvHelper.Configuration.MemberMap`2[[DataTest, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[System.UInt32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]::.ctor' for which no ahead of time (AOT) code was generated.
      at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00000] in <00000000000000000000000000000000>:0 
      at System.Reflection.MonoCMethod.Invoke (System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0 
      at System.RuntimeType.CreateInstanceImpl (System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes, System.Threading.StackCrawlMark& stackMark) [0x00000] in <00000000000000000000000000

The error seems to be due to the AOT limitations mentioned by Unity Technology.

This issue appears to be a difficult problem to solve unless Unity Technology has modified il2cpp.

JoshClose commented 5 years ago

Let's try not using it at all then. You can create an ObjectResolver that just returns null. If you just use the GetField methods, none of the object creation will happen, and I think you should be ok.

Example:

void Main()
{
    ObjectResolver.Current = new ObjectResolver(type => true, (type, args) => null);
    var s = new StringBuilder();
    s.AppendLine("Id,Name");
    s.AppendLine("1,one");
    s.AppendLine("2,two");
    using (var reader = new StringReader(s.ToString()))
    using (var csv = new CsvReader(reader))
    {
        var records = new List<Foo>();
        csv.Read();
        csv.ReadHeader();
        while (csv.Read())
        {
            var record = new Foo
            {
                Id = csv.GetField<int>(nameof(Foo.Id)),
                Name = csv.GetField<string>(nameof(Foo.Name))
            };
            records.Add(record);
        }

        records.Dump();
    }
}

public class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
}
ninh-mech commented 2 years ago

You might be able to create your own ObjectResolver implementation that uses Activator.CreateInstance instead. Try putting this code before you create the CsvReader instance and see if that works.

ObjectResolver.Current = new ObjectResolver(type => true, Activator.CreateInstance);

Thank you for answer. I've tried putting the code and running it, but I get this error.

05-15 12:12:38.012 30243-30292/? E/Unity: ExecutionEngineException: Attempting to call method 'CsvHelper.Configuration.MemberMap`2[[DataTest, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[System.UInt32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]::.ctor' for which no ahead of time (AOT) code was generated.
      at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00000] in <00000000000000000000000000000000>:0 
      at System.Reflection.MonoCMethod.Invoke (System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <00000000000000000000000000000000>:0 
      at System.RuntimeType.CreateInstanceImpl (System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes, System.Threading.StackCrawlMark& stackMark) [0x00000] in <00000000000000000000000000

The error seems to be due to the AOT limitations mentioned by Unity Technology.

This issue appears to be a difficult problem to solve unless Unity Technology has modified il2cpp.

Hi @ghfhgh67, Did you find the way to make CSVHelper working on mobile platform?