|
|
|
11-06-2018, 02:18 AM
|
#1
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Can extension-provided API functions return strings longer than 1024 characters?
REAPER itself seems to use a "NeedBig" modifier in the parameter name, if a long string is required:
Code:
C++: int GetProjExtState(ReaProject* proj, const char* extname, const char* key, char* valOutNeedBig, int valOutNeedBig_sz)
EEL: int GetProjExtState(ReaProject proj, "extname", "key", #val)
Lua: integer retval, string val = reaper.GetProjExtState(ReaProject proj, string extname, string key)
Python: (Int retval, ReaProject proj, String extname, String key, String valOutNeedBig, Int valOutNeedBig_sz) = RPR_GetProjExtState(proj, extname, key, valOutNeedBig, valOutNeedBig_sz)
When I tried to use "NeedBig", the API interpreter appears to recognize the modifier and, in the case of Lua, the modifier is removed from the parameter name in the API documentation and in the IDE help (as in the code above, "nameOutNeedBig" simply becomes "name").
However, the string size passed to the function is still only 1024.
|
|
|
11-06-2018, 12:11 PM
|
#3
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,621
|
CFillion mentioned at some point, that he knows now how to do it without using Faststring now, but I can't find the post anymore...
|
|
|
11-06-2018, 12:52 PM
|
#4
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Thanks for reminding me about SWS's FastStrings.
I checked out how GetFastString manages to return long strings, and it seems that API functions can return long strings if the C++ function has the char* as the return value, instead of a parameter with an "Out" suffix:
(EDIT: const char*, not simply char*.)
Code:
const char* myFunction()
instead of:
Code:
void myFunction(char* myStringOut, int myStringOut_sz)
When the return value is a const char*, the char* can point to a buffer of any size.
I was skeptical about returning a pointer to temporary data, but it seems that REAPER immediately converts the C string to a proper Lua string, so the buffer can be overwritten in the next function call without problems.
This technique has the limitation that the returned string must be the first return value. Usually, functions that return a boolean place the boolean first, similar to MIDI_GetAllEvts:
Code:
boolean retval, string buf = reaper.MIDI_GetAllEvts(MediaItem_Take take, string buf)
Last edited by juliansader; 11-07-2018 at 12:51 AM.
|
|
|
11-06-2018, 02:37 PM
|
#5
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
That's useful info thanks (as I remembered I also have some functions in SWS pull requests returning a FastString, will change to this technique).
Last edited by nofish; 11-06-2018 at 02:48 PM.
|
|
|
11-06-2018, 02:49 PM
|
#6
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 4,937
|
Also, Lua ReaScripts can override the default buffer size by setting the optional hidden *_sz parameter (like in Python, where it's mandatory).
Code:
reaper.myFunction('') -- default (1024)
reaper.myFunction('', 4096) -- custom
Quote:
Originally Posted by juliansader
I was skeptical about returning a pointer to temporary data, but it seems that REAPER immediately converts the C string to a proper Lua string, so the buffer can be overwritten in the next function call without problems.
|
Can't return the address of a temporary buffer though. It must still point to valid data when REAPER copies the string after the function has returned (and destroyed all temporaries). The string must be freed after that.
Depending on what your function does, another possibility could be to have it calculate and give the data by small chunks. Like how the various Enum* API functions give one row at a time (which is often the best solution when having to return a table).
Last edited by cfillion; 11-06-2018 at 04:14 PM.
|
|
|
11-08-2018, 02:03 AM
|
#7
|
Human being with feelings
Join Date: Jul 2009
Posts: 3,714
|
Quote:
Originally Posted by cfillion
Also, Lua ReaScripts can override the default buffer size by setting the optional hidden *_sz parameter (like in Python, where it's mandatory).
|
Great! I didn't know about this hidden parameter.
I will add this tip to my API functions' help text.
|
|
|
11-08-2018, 07:47 AM
|
#8
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,721
|
Internally, NeedBig uses a reallocator function to grow buffers up from 1k on demand. Extending it for the next builds so that you can use this function:
Code:
bool (*realloc_cmd_ptr)(char **ptr, int *ptr_size, int new_size);
In your function which has the NeedBig flag, if it is passed a char* bufNeedBig and int bufNeedBig_sz, and bufNeedBig_sz isn't big enough, you'd do this:
Code:
if (!realloc_cmd_ptr(&bufNeedBig, &bufNeedBig_sz, requested_size))
{
//error!
}
assert(bufNeedBig_sz >= requested_size);
...
Last edited by Justin; 11-08-2018 at 08:19 AM.
|
|
|
11-08-2018, 02:29 PM
|
#9
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 4,937
|
Awesome!
|
|
|
11-08-2018, 08:08 PM
|
#10
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,721
|
Also making it so you can append Need8192 etc and it will try to make 8192 bytes available (if you don't need dynamically-sized).
|
|
|
11-09-2018, 05:26 AM
|
#11
|
Human being with feelings
Join Date: May 2017
Location: Leipzig
Posts: 6,621
|
Thnx Justin
|
|
|
11-13-2018, 06:49 AM
|
#12
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,721
|
This is in yesterday's +dev build, if you want to start on testing... (or I suppose I could get it working in sws...)
|
|
|
11-20-2018, 08:03 PM
|
#13
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,721
|
Some slight changes to realloc_cmd_ptr in 5.962+dev1120 -- calling it will cause Lua to return the full resized length (so you can embed nul characters in there). There are other fixes/optimizations related to this, so if anybody is using this, please test thoroughly again! Thanks!
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 12:19 PM.
|