Я попытался сгенерировать сборку, которая вызывает библиотеку dll, но наткнулся на неразрешимую ошибку.
Я скомпилировал sll.dll, написанную на c ++ (только один класс — StackInt) и скомпилированный с параметрами CLR x86 Release.
#pragma once
// sll.dll
using namespace System;
namespace SLCollections {
public ref class StackInt
{
private:
array< Int32 >^ data;
Int32 size, capacity;
void grow() {
array< Int32 >^ newdata = gcnew array< Int32 >(capacity << 1);
for (Int32 i = 0; i < capacity; i++) {
newdata[i] = data[i];
}
capacity <<= 1;
data = newdata;
}
public:
StackInt() : size(0), capacity(2), data(gcnew array< Int32 >(2)) {}
void push(Int32 item) {
if (capacity >= size) {
grow();
}
data[size++] = item;
}
Int32 pop() {
return data[--size];
}
Int32 top() {
return data[size - 1];
}
bool isEmpty() {
return size == 0;
}
};
}
Я хочу использовать эту библиотеку в динамически генерируемой сборке, написанной на C # с использованием Reflection Emit и скомпилированной с параметрами конфигурации x86 Release. Код C # использует sll.dll (ссылается на dll):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection.Emit;
using SLCollections;
using System.Reflection;
namespace Generator
{
class Program
{
static void Main(string[] args)
{
string moduleName = "test.exe";
try
{
// worked code!
//StackInt stack = new StackInt();
//stack.push(10);
AssemblyName name = new AssemblyName(System.IO.Path.GetFileNameWithoutExtension(moduleName));
AssemblyBuilder asmb = AppDomain.CurrentDomain
.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder modb = asmb.DefineDynamicModule(moduleName);
TypeBuilder typeBuilder = modb.DefineType("Foo");
MethodBuilder methb = typeBuilder.DefineMethod("Main",
MethodAttributes.Static, typeof(void),
Type.EmptyTypes);
ILGenerator il = methb.GetILGenerator();
Type stackType = typeof(StackInt);
LocalBuilder localStackBuilder = il.DeclareLocal(stackType);
Type[] t = new Type[0];
il.Emit(OpCodes.Newobj,
stackType.GetConstructor(t));
il.Emit(OpCodes.Stloc, localStackBuilder);
il.Emit(OpCodes.Ldloc, localStackBuilder);
MethodInfo pushMethod = stackType.GetMethod(
"push", new Type[] { typeof(int) });
il.Emit(OpCodes.Ldc_I4_4);
il.Emit(OpCodes.Callvirt, pushMethod);
il.Emit(OpCodes.Pop);
// return
il.Emit(OpCodes.Ret);
typeBuilder.CreateType();
modb.CreateGlobalFunctions();
asmb.SetEntryPoint(methb);
asmb.Save(moduleName);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
}
}
}
Можно создать объект класса StackInt, который входит в sll.dll, и вызывать его методы с помощью using SLCollections
директивы. Когда я компилирую и сохраняю сборку, все в порядке. Однако сборка test.exe запускается с ошибкой:
System.BadImageFormatException was unhandled Message:
An unhandled exception of type 'System.BadImageFormatException'
occurred in mscorlib.dll Additional information:
Failed to load file or assembly
"SLL, Version=1.0.6354.41871, Culture=neutral, PublicKeyToken=null"or one of their dependencies.
An attempt was made to load a program that has an incorrect format.
Разобранный код из сгенерированной сборки в порядке.
Где я ошибся?
Задача ещё не решена.
Других решений пока нет …