【问题标题】:How to import Rust command functions into C#?如何将 Rust 命令函数导入 C#?
【发布时间】:2022-12-06 17:22:30
【问题描述】:

我想在这里导入这两个命令函数,并在我的C#程序中调用它们。有了这些功能,我想创建 .pack 文件,然后向其中添加文件夹。我对 Rust 一无所知,但我知道我需要在这些函数后面定义 extern "cdecl" fn#[no_mangle],但仅此而已。困扰我的是在 C# 中调用它时我将使用哪些参数。

/// This function creates a new empty Pack with the provided path.
pub fn create(config: &Config, path: &Path) -> Result<()> {
    if config.verbose {
        info!("Creating new empty Mod Pack at {}.", path.to_string_lossy().to_string());
    }

    match &config.game {
        Some(game) => {
            let mut file = BufWriter::new(File::create(path)?);
            let mut pack = Pack::new_with_version(game.pfh_version_by_file_type(PFHFileType::Mod));
            pack.encode(&mut file, &None)?;
            Ok(())
        }
        None => Err(anyhow!("No Game provided.")),
    }
}
  • 那么我将在我的 C# 程序中使用哪些参数??? (注意:此代码来自免费的开源应用程序 RPFM)
   /// This function adds the provided files/folders to the provided Pack.
   pub fn add(config: &Config, schema_path: &Option<PathBuf>, pack_path: &Path, file_path: &[(PathBuf, String)], folder_path: &[(PathBuf, String)]) -> Result<()> {
       if config.verbose {
           info!("Adding files/folders to a Pack at {}.", pack_path.to_string_lossy().to_string());
           info!("Tsv to Binary is: {}.", schema_path.is_some());
       }
   
       // Load the schema if we try to import tsv files.
       let schema = if let Some(schema_path) = schema_path {
           if schema_path.is_file() {
   
               // Quick fix so we can load old schemas. To be removed once 4.0 lands.
               let _ = Schema::update(schema_path, &PathBuf::from("schemas/patches.ron"), &config.game.as_ref().unwrap().game_key_name());
               Some(Schema::load(schema_path)?)
           } else {
               warn!("Schema path provided, but it doesn't point to a valid schema. Disabling `TSV to Binary`.");
               None
           }
       } else { None };
   
       let pack_path_str = pack_path.to_string_lossy().to_string();
       let mut reader = BufReader::new(File::open(pack_path)?);
       let mut extra_data = DecodeableExtraData::default();
   
       extra_data.set_disk_file_path(Some(&pack_path_str));
       extra_data.set_timestamp(last_modified_time_from_file(reader.get_ref())?);
       extra_data.set_data_size(reader.len()?);
   
       let mut pack = Pack::decode(&mut reader, &Some(extra_data))?;
   
       for (folder_path, container_path) in folder_path {
           pack.insert_folder(folder_path, container_path, &None, &schema)?;
       }
   
       for (file_path, container_path) in file_path {
           pack.insert_file(file_path, container_path, &schema)?;
       }
   
       pack.preload()?;
   
       let mut writer = BufWriter::new(File::create(pack_path)?);
       pack.encode(&mut writer, &None)?;
   
       if config.verbose {
           info!("Files/folders added.");
       }
   
       Ok(())
   } ```

【问题讨论】:

  • 我会注意到,如果您要使用的代码很小,那么只移植这些方法可能会更快更容易。 C# 与非 .Net 语言的互操作可能有点困难,如果您正在处理对象,情况会变得更糟,因为您的大多数参数似乎都是如此。
  • @JonasH 所以你是说在我的 C# 中创建那些相同的函数?

标签: c# rust ffi


【解决方案1】:

要在 C# 中调用这些函数,您首先需要将它们编译成一个可供 C# 使用的库。为此,您需要使用 Rust 编译器将它们编译成动态库。

完成此操作后,您可以使用 DllImport 属性在 C# 中导入库。您需要指定编译库的路径,以及函数名称和它们各自的签名。

这是您如何执行此操作的示例:

[DllImport("path/to/library.dll")]
public static extern IntPtr create(ref Config config, ref Path path);

[DllImport("path/to/library.dll")]
public static extern IntPtr add(ref Config config, ref Option schemaPath, ref Path packPath, ref FilePath[] filePath, ref FolderPath[] folderPath);

然后,您就可以像这样在 C# 代码中调用这些函数:

var result1 = create(ref myConfig, ref myPath);
var result2 = add(ref myConfig, ref mySchemaPath, ref myPackPath, ref myFilePaths, ref myFolderPaths);

请注意,确切的参数类型和函数签名可能因 Rust 函数的实现而异。您可能需要相应地调整 C# 声明。

【讨论】:

    猜你喜欢
    • 2010-11-08
    • 1970-01-01
    • 2020-02-06
    • 2013-12-23
    • 2016-06-14
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多