SOLVED OpenInputStream() works incorrect.

Language: C++
Platform: Windows

Hello.
I am trying to realize the downloading of a future updates of my C++ plugin.
I want to achieve in result the posibility to download the new file or folder from my web adress and replace the old one.
For it I am using this code snipped: https://developers.maxon.net/docs/Cinema4DCPPSDK/html/page_maxonapi_files_inputstream.html#page_maxonapi_files_inputstream_use
("// This example loads a file from the web and saves it to the local file system.")

But I receive an error on this line:

const maxon::InputStreamRef inputStream = webFile.OpenInputStream() iferr_return;
  • Error (active) E0312 no suitable user-defined conversion from "maxon::MacroArgType<void (maxon::Resultmaxon::InputStreamRef)>" to "const maxon::InputStreamRef" exists*

What am I doing wrong?

On SDK help search there is no a link to a "InputStreamRef".

The code:

const maxon::Url webFile = (maxon::Url("https://www.mysite.com/Somevideo.mp4"_s))iferr_return; // just for tests
    
    // check if the given URL references a file on the web
    const maxon::UrlScheme scheme = webFile.GetScheme();
    const maxon::Bool      isHTTP = scheme == maxon::URLSCHEME_HTTP;
    const maxon::Bool      isHTTPS = scheme == maxon::URLSCHEME_HTTPS;

    if (isHTTP || isHTTPS)
    {
        // read data 
        // input stream
        webFile.OpenInputStream();
        const maxon::InputStreamRef inputStream = webFile.OpenInputStream() iferr_return;
        const maxon::Int length = inputStream.GetStreamLength() iferr_return;

        maxon::BaseArray<maxon::Char> data;
        data.Resize(length) iferr_return;

        inputStream.Read(data) iferr_return;
        inputStream.Close() iferr_return;

        // save data to file

        // prepare file name
        const maxon::Url localFile = (sad)iferr_return;
        const maxon::Url localFile = (targetFolder + webFile.GetName())iferr_return;
        // output stream
        const maxon::OutputStreamRef outputStream = localFile.OpenOutputStream() iferr_return;
        // write to file
        outputStream.Write(data) iferr_return;
        outputStream.Close() iferr_return;
    }

Hello @yaya,

thank you for reaching out to us. Your example does build for me in R23, at least regarding the mentioned line of code:

const maxon::InputStreamRef inputStream = webFile.OpenInputStream() iferr_return;

Your example is however incomplete, it is missing the include statement to include iostreams.h which is likely causing your error. But there should be more errors for you in this stretch of code, since for example the line const maxon::Url webFile = (maxon::Url("https://www.mysite.com/Somevideo.mp4"_s))iferr_return is also incorrect. Find a commented example at the end of my posting for details.

On SDK help search there is no a link to a "InputStreamRef".

The maxon API does provide in C++ a managed memory environment, i.e., garbage collection, akin to managed languages like C# or Python. Which means all objects are split into the actual object instance and references to that instance. The object instance is then reference counted and deallocated once there are no references to it anymore. So, when you have a ThingRef, it is actually just a reference to an instance of a ThingInterface (at least most of the time, copy-on-write object references do not have the Ref postfix, i.e., the reference for a COW ThingInterface would be called Thing). The Doxygen parser (the tool we are using for documentation) does struggle heavily with all the metaprogramming we do and cannot properly ingest Ref entities. This is a bit tricky subject we are aware of and working on to, but this will take some time.

Long story short, you would have to search here for InputStreamInterface. There is also our Entity Creation Manual which does expand a bit on the topic of interfaces and their references.

If you continue to have problems, please make sure to post your full code and not just a snippet, as it otherwise mostly guesswork for us to figure out where your problem lies.

Cheers,
Ferdinand

// You must include this header in order to have access to the full interface definitions.
#include "maxon\iostreams.h"

maxon::Result<void> SomeFunction()
{
  iferr_scope;

  // The iferr_return here was incorrect. In our example it is required because we concatenate there
  // two urls. UrlInterface.operator+ is a maxon::Result, i.e., requires error handling. Just 
  // initializing a Url does not have any error handling and therefor requires no iferr_return.
  const maxon::Url url("https://www.mysite.com/Somevideo.mp4"_s);
  const maxon::UrlScheme scheme = url.GetScheme();
  const maxon::Bool isHTTP = scheme == maxon::URLSCHEME_HTTP;
  const maxon::Bool isHTTPS = scheme == maxon::URLSCHEME_HTTPS;

  if (isHTTP || isHTTPS)
  {
    const maxon::InputStreamRef inputStream = url.OpenInputStream() iferr_return;
    const maxon::Int length = inputStream.GetStreamLength() iferr_return;

    maxon::BaseArray<maxon::Char> data;
    data.Resize(length) iferr_return;

    inputStream.Read(data) iferr_return;
    inputStream.Close() iferr_return;

    // trgetUrl was not defined in your/our example, so I did redefine it here as someUrl.
    const maxon::Url someUrl("https://www.yoursite.com/"_s);
    // This will be "https://www.yoursite.com/Somevideo.mp4", i.e., GetName returns the last 
    // component of a Url, e.g., "Somevideo.mp4" in this case. Here we need the iferr_return, since 
    // UrlInterface.operator+ can fail, i.e., return an error.
    const maxon::Url anotherUrl = (someUrl + url.GetName()) iferr_return;
    const maxon::OutputStreamRef outputStream = anotherUrl.OpenOutputStream() iferr_return;

    outputStream.Write(data) iferr_return;
    outputStream.Close() iferr_return;
  }
  return maxon::OK;
}

Hello @yaya,

thank you for reaching out to us. Your example does build for me in R23, at least regarding the mentioned line of code:

const maxon::InputStreamRef inputStream = webFile.OpenInputStream() iferr_return;

Your example is however incomplete, it is missing the include statement to include iostreams.h which is likely causing your error. But there should be more errors for you in this stretch of code, since for example the line const maxon::Url webFile = (maxon::Url("https://www.mysite.com/Somevideo.mp4"_s))iferr_return is also incorrect. Find a commented example at the end of my posting for details.

On SDK help search there is no a link to a "InputStreamRef".

The maxon API does provide in C++ a managed memory environment, i.e., garbage collection, akin to managed languages like C# or Python. Which means all objects are split into the actual object instance and references to that instance. The object instance is then reference counted and deallocated once there are no references to it anymore. So, when you have a ThingRef, it is actually just a reference to an instance of a ThingInterface (at least most of the time, copy-on-write object references do not have the Ref postfix, i.e., the reference for a COW ThingInterface would be called Thing). The Doxygen parser (the tool we are using for documentation) does struggle heavily with all the metaprogramming we do and cannot properly ingest Ref entities. This is a bit tricky subject we are aware of and working on to, but this will take some time.

Long story short, you would have to search here for InputStreamInterface. There is also our Entity Creation Manual which does expand a bit on the topic of interfaces and their references.

If you continue to have problems, please make sure to post your full code and not just a snippet, as it otherwise mostly guesswork for us to figure out where your problem lies.

Cheers,
Ferdinand

// You must include this header in order to have access to the full interface definitions.
#include "maxon\iostreams.h"

maxon::Result<void> SomeFunction()
{
  iferr_scope;

  // The iferr_return here was incorrect. In our example it is required because we concatenate there
  // two urls. UrlInterface.operator+ is a maxon::Result, i.e., requires error handling. Just 
  // initializing a Url does not have any error handling and therefor requires no iferr_return.
  const maxon::Url url("https://www.mysite.com/Somevideo.mp4"_s);
  const maxon::UrlScheme scheme = url.GetScheme();
  const maxon::Bool isHTTP = scheme == maxon::URLSCHEME_HTTP;
  const maxon::Bool isHTTPS = scheme == maxon::URLSCHEME_HTTPS;

  if (isHTTP || isHTTPS)
  {
    const maxon::InputStreamRef inputStream = url.OpenInputStream() iferr_return;
    const maxon::Int length = inputStream.GetStreamLength() iferr_return;

    maxon::BaseArray<maxon::Char> data;
    data.Resize(length) iferr_return;

    inputStream.Read(data) iferr_return;
    inputStream.Close() iferr_return;

    // trgetUrl was not defined in your/our example, so I did redefine it here as someUrl.
    const maxon::Url someUrl("https://www.yoursite.com/"_s);
    // This will be "https://www.yoursite.com/Somevideo.mp4", i.e., GetName returns the last 
    // component of a Url, e.g., "Somevideo.mp4" in this case. Here we need the iferr_return, since 
    // UrlInterface.operator+ can fail, i.e., return an error.
    const maxon::Url anotherUrl = (someUrl + url.GetName()) iferr_return;
    const maxon::OutputStreamRef outputStream = anotherUrl.OpenOutputStream() iferr_return;

    outputStream.Write(data) iferr_return;
    outputStream.Close() iferr_return;
  }
  return maxon::OK;
}