Python app unable to call a method from C# that uses a third party library (Can't Find Gurobi Dependency)

19 Views Asked by At

My python app is not able to call a method from C# that uses a third party library (namely, Gurobi).

My project structure:

  1. a C# Library Project that is an Algorithm (in some parts of it I use Gurobi (a library of its own))
  2. a Python App, which is connected to the C# script by a C# DLL. The connection works for simple method like addition and multiplication.

When I call a more sophisticated method from the C# library in python (i.e. one with a Gurobi method implemented), I am not able run the method and get a FileNotFoundException. I have tried adding the DLL of Gurobi itself but it did not work.

Upon calling the method with the implicit Gurobi code, I get:

Error in app visualization

How can I add the gurobi DLL and Newtonsoft.Json DLLs to my python code?

  1. I have tried manually adding the gurobi dll, yet the C# project as a Library output has no gurobi dll within the bin folder (i.e. where the C# library dll is constructed "alnslib.dll").
  2. I also tried establishing the connection via exe instead of Library, it did not work.

This is my python code:

import clr

# Add references to the DLLs
clr.AddReference("bin/Debug/net7.0/alnslib")

# This attempt did not work
# clr.AddReference("bin/Debug/net7.0/gurobi100.netstandard20.dll")
# import gurobi100

from alnslib import Class1
import streamlit as st
from ctypes import *
import json

st.title('Testing C# DLL')

# Simple Maths Calculation connections
calculator = Class1()
st.write(calculator.Add(5, 5))
st.write(calculator.Multiply(5, 5))

# SumList method
numbers = [1.5, 2.3, 4.7, 3.1]
num_array = (c_double * len(numbers))(*numbers) # This Notation is new
result = calculator.SumList(num_array)

st.write("Sum of the numbers:", result)

# SumList method with a 2x2 matrix
matrix = [
    [2.5, 2.5],
    [5, 6.0]
]

# Flatten the 2D Python list
flat_matrix = [item for sublist in matrix for item in sublist]

# Convert the flattened Python list to a C-style array of doubles
num_array_2d = (c_double * len(flat_matrix))(*flat_matrix)

# Call the SumList method with the 1D array
result_matrix_sum = calculator.SumList(num_array_2d)

st.write("Sum of the 2D matrix:", result_matrix_sum)

# JSON processing method
json_data = {
    "key1": 5,
    "Test": 2,
}

# Convert JSON object to a string
json_string = json.dumps(json_data)

# Call the ProcessJson method with the JSON string
result_json_processing = calculator.ProcessJson(json_string)

st.write(result_json_processing)

st.write(calculator.SolveLinearProgrammingProblem())

# st.write(calculator.ProcessJsonStringToJson(json_string))

This is my C# code:

using System;
using Newtonsoft.Json.Linq;
using Gurobi;

namespace alnslib
{
    public class Class1
    {
        // Method to add two numbers
        public int Add(int a, int b)
        {
            return a + b;
        }

        // Method to multiply two numbers
        public int Multiply(int a, int b)
        {
            return a * b;
        }

        // Method to sum an array of floating-point numbers
        public double SumList(double[] numbers)
        {
            double sum = 0;

            foreach (var number in numbers)
            {
                sum += number;
            }

            return sum;
        }

        // Method to sum a 2D array of floating-point numbers
        public double SumListTwo(double[,] matrix)
        {
            double sum = 0;

            for (int i = 0; i < matrix.GetLength(0); i++)
            {
                for (int j = 0; j < matrix.GetLength(1); j++)
                {
                    sum += matrix[i, j];
                }
            }

            return sum;
        }

        // Method to process a JSON string
        public string ProcessJson(string jsonString)
        {

            // Your processing logic here
            return "Processed: " + jsonString;
        }

        // Method to process a JSON string
        public string ProcessJsonStringToJson(string jsonString)
        {
            // Parse the JSON string to create a JObject
            JObject jsonObject = JObject.Parse(jsonString);

            // Now you have a JObject to work with
            // Your processing logic here

            // Example: Add a new key-value pair to the JObject
            jsonObject["NewKey"] = "NewValue";

            // Convert the modified JObject back to a string
            string modifiedJsonString = jsonObject.ToString();

            // Return the modified JSON string
            return "Processed: " + modifiedJsonString;
        }

        // Method to solve a simple linear programming problem using Gurobi
        
        public string SolveLinearProgrammingProblem()
        {
            try
            {
                using (GRBEnv env = new GRBEnv())
                {
                    // Create a Gurobi model
                    using (GRBModel model = new GRBModel(env))
                    {
                        // Add variables
                        GRBVar x = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "x");
                        GRBVar y = model.AddVar(0.0, 1.0, 0.0, GRB.BINARY, "y");

                        // Set objective function
                        GRBLinExpr objExpr = new GRBLinExpr();
                        objExpr.AddTerm(2.0, x);
                        objExpr.AddTerm(1.0, y);
                        model.SetObjective(objExpr, GRB.MAXIMIZE);

                        // Add constraint: x + 2y <= 1
                        GRBLinExpr constraintExpr = new GRBLinExpr();
                        constraintExpr.AddTerm(1.0, x);
                        constraintExpr.AddTerm(2.0, y);
                        model.AddConstr(constraintExpr, GRB.LESS_EQUAL, 1.0, "constraint1");

                        // Optimize the model
                        model.Optimize();

                        // Return the solution as a string
                        return $"Optimal Objective Value: {model.ObjVal}, Optimal x: {x.Get(GRB.DoubleAttr.X)}, Optimal y: {y.Get(GRB.DoubleAttr.X)}";
                    }
                }
            }
            catch (GRBException e)
            {
                return $"Error code: {e.ErrorCode}. {e.Message}";
            }
        }

        // Main method to execute the Gurobi linear programming problem solver
        public static void Main()
        {
            Class1 myClass = new Class1();
            
            // Call the Gurobi solver method
            string result = myClass.SolveLinearProgrammingProblem();

            // Print or log the result
            Console.WriteLine(result);

            // Optionally, you can wait for user input before closing the console window
            Console.WriteLine("Press Enter to exit...");
            Console.ReadLine();
        }
        
    }
}

This is my C# Project Configuration .csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Library</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageReference Include="Gurobi.Optimizer" Version="10.0.3" />
  </ItemGroup>

</Project>
0

There are 0 best solutions below